How do I copy a HttpRequest to another web service? - c#

I have two identical web services currently installed on the same PC for testing purposes. A request that is received by the first service, is suposed go to the second one as well. My intention was to do this using a HttpModule. I handle the request during application.BeginRequest.
public void AsyncForwardRequest(HttpRequest request)
{
try
{
// Prepare web request...
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(WSaddress);
req.Credentials = CredentialCache.DefaultCredentials;
req.Headers.Add("SOAPAction", request.Headers["SOAPAction"]);
req.ContentType = request.Headers["Content-Type"];
req.Accept = request.Headers["Accept"];
req.Method = request.HttpMethod;
// Send the data.
long posStream = request.InputStream.Position;
long len = request.InputStream.Length;
byte[] buff = new byte[len];
request.InputStream.Seek(0, SeekOrigin.Begin);
if (len < int.MaxValue && request.InputStream.Read(buff, 0, (int)len) > 0)
{
using (Stream stm = req.GetRequestStream())
{
stm.Write(buff, 0, (int)len);
}
request.InputStream.Position = posStream;
DebugOutputStream(request.InputStream);
request.InputStream.Seek(0, SeekOrigin.Begin);
IAsyncResult result = (IAsyncResult)req.BeginGetResponse(new AsyncCallback(RespCallback), req);
}
}
catch (Exception ex)
{
App.Error2(String.Format("RequestDuplicatorModule - BeginRequest; ERROR begin request: {0}", ex.Message), ex);
}
private static void RespCallback(IAsyncResult asynchronousResult)
{
try
{
// State of request is asynchronous.
var req = (HttpWebRequest)asynchronousResult.AsyncState;
WebResponse resp = (HttpWebResponse)req.EndGetResponse(asynchronousResult);
Stream responseStream = resp.GetResponseStream();
System.IO.Stream stream = responseStream;
Byte[] arr = new Byte[1024 * 100];
stream.Read(arr, 0, 1024 * 100);
if (arr.Length > 0)
{
string body = (new ASCIIEncoding()).GetString(arr);
Debug.Print(body);
}
}
catch (WebException ex)
{
App.Error2(String.Format("RequestDuplicatorModule - BeginRequest; ERROR begin request: {0}", ex.Message), ex);
}
}
This (HttpWebResponse)req.EndGetResponse(asynchronousResult) throws an exception: 500 Internal Server Error and fails. The original request goes through fine.
request.InnerStream:
...
Does this have anything to do with the web service addresses being different? In my case they're:
http://localhost/WS/service.asmx
http://localhost/WS_replicate/service.asmx

I would at least implement this, to be able to read the content of a httpwebrequest that has a status 500:
catch (WebException ex)
{
HttpWebResponse webResponse = (HttpWebResponse)ex.Response;
Stream dataStream = webResponse.GetResponseStream();
if (dataStream != null)
{
StreamReader reader = new StreamReader(dataStream);
response = reader.ReadToEnd();
}
}
Not answering your question though, i would suggest having a simple amsx that reads the request, and posts the request to the two different web services. If you need some code for that let me know.
Additional advantages would be that the asmx will be easier to support for the developer as well as the one dealing with the deployment. You could add configuration options to make the actual url's dynamic.

Was able to modify the AsyncForwardRequest method so that I can actually edit the SoapEnvelope itself:
string buffString = System.Text.UTF8Encoding.UTF8.GetString(buff);
using (Stream stm = req.GetRequestStream())
{
bool stmIsReadable = stm.CanRead; //false, stream is not readable, how to get
//around this?
//solution: read Byte Array into a String,
//modify <wsa:to>, write String back into a
//Buffer, write Buffer to Stream
buffString = buffString.Replace("http://localhost/WS/Service.asmx", WSaddress);
//write modded string to buff
buff = System.Text.UTF8Encoding.UTF8.GetBytes(buffString);
stm.Write(buff, 0, (int)buff.Length);
}

Related

C# HttpWebRequest does not work with https. The program gets stuck on the line HttpWebResponse execute

Below is the link which is https and return the JSON. but the code gets stuck on the HttpWebResponse and nothing happens. It does not go in the catch block also.
public static string GetWebSource(string URL)
{
StringBuilder sb = new StringBuilder();
if (URL != "")
{
// used to build entire input
try
{
// used on each read operation
byte[] buf = new byte[8192];
// prepare the web page we will be asking for
HttpWebRequest request = (HttpWebRequest)
WebRequest.Create("https://www.nseindia.com/api/option-chain-indices?symbol=NIFTY");
request.ContentType = "application/json";
request.Method = "GET";
// execute the request
HttpWebResponse response = (HttpWebResponse)
request.GetResponse();
// we will read data via the response stream
Stream resStream = response.GetResponseStream();
string tempString = null;
int count = 0;
do
{
// fill the buffer with data
count = resStream.Read(buf, 0, buf.Length);
// make sure we read some data
if (count != 0)
{
// translate from bytes to ASCII text
tempString = Encoding.UTF8.GetString(buf, 0, count);
// continue building the string
sb.Append(tempString);
}
}
while (count > 0); // any more data to read?
}
catch (Exception ex)
{
}
}
// print out page source
return sb.ToString();
}

Error : 413 Request Entity Too Large in C# WinForm Application

I am trying to send JSON Object to Server for data synchronization.
This JSON object contain non-synchronized images and their data.
Real problem is not with he JSON or the Synchronization code.
But it is with the size of the Request i am sending to the server.
if the size cross the limit 1.1MB then i Got this message
The remote server returned an error: (413) Request Entity Too Large.
Please Help me. It is pur C# application not the WCF application.
Domain Hosting provider is Godady.com.
Using Apache server and PHP script.
Every this is working fine for smaller size. but it give exception error when size cross 1.1MB.
Here is My Request Code.
public string SubmitData(string poststring)
{
string result ="false";
if (poststring.ToLower() == "empty")
{
result = "empty";
return result;
}
try
{
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = poststring;
byte[] data = encoding.GetBytes(postData);
WebRequest request = WebRequest.Create("http://blunor.com/dark/data.php");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Credentials = CredentialCache.DefaultCredentials;
request.ContentLength = data.Length;
Stream stream = request.GetRequestStream();
showMessageBox(data.Length.ToString(), "Message", 1);
stream.Write(data, 0, data.Length);
stream.Close();
WebResponse response = request.GetResponse();
stream = response.GetResponseStream();
StreamReader sr = new StreamReader(stream);
// this block of code check if response is +ve or negtive..
string res_num = sr.ReadToEnd();
if (res_num == "1")
{
result = "true";
}
else
{
result = "false";
}
//block end here.....
sr.Close();
stream.Close();
return result;
}
catch (Exception ex)
{
MessageBox.Show("Error : " + ex.Message);
}
return result;
}
For Server php post_max_size = 128M and Upload_max_filesize = 32M
Please Help......

HttpWebRequest Issue to remote server

I'm trying to upload files to a remote server (windows server 2008 R2) from my asp.net 1.1 (C#) Windows application (I know.. It's really old, sadly, that's what we have). When I try to upload, it's giving me an error: "The remote server returned an error: (404) Not Found.".
Here's the code I'm using:
Any ideas?
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uploadUrl);
req.Credentials = new NetworkCredential(uName,pwd);
req.Method = "PUT";
req.AllowWriteStreamBuffering = true;
// Retrieve request stream
Stream reqStream = req.GetRequestStream();
// Open the local file
FileStream rdr = new FileStream(txt_filename.Text, FileMode.Open);
// Allocate byte buffer to hold file contents
byte[] inData = new byte[4096];
// loop through the local file reading each data block
// and writing to the request stream buffer
int bytesRead = rdr.Read(inData, 0, inData.Length);
while (bytesRead > 0)
{
reqStream.Write(inData, 0, bytesRead);
bytesRead = rdr.Read(inData, 0, inData.Length);
}
rdr.Close();
reqStream.Close();
req.GetResponse();
The uploadUrl is like this: http://10.x.x.x./FolderName/Filename
Please use "POST" method instead of "PUT" and I guess it will work.
Edit:
Check the code below, it will help you.
public void UploadFile()
{
string fileUrl = #"enter file url here";
string parameters = #"image=" + Convert.ToBase64String(File.ReadAllBytes(fileUrl));
WebRequest req = WebRequest.Create(new Uri("location url here"));
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(parameters);
try
{
req.ContentLength = bytes.Length;
Stream s = req.GetRequestStream();
s.Write(bytes, 0, bytes.Length);
s.Close();
}
catch (WebException ex)
{
throw ex; //Request exception.
}
try
{
WebResponse res = req.GetResponse();
StreamReader sr = new StreamReader(req.GetResponseStream());
}
catch (WebException ex)
{
throw ex; //Response exception.
}
}
Enter fileUrl variable correctly and take care of uri while creating WebRequest instance, write the url of the locating folder.

ProtocolViolationException while sending POST request

I have read other similar questions and tried the solutions from those questions, but since that did not work, hence I am posting this here.
When I send POST request below, it fails with the following error message:
System.Net.ProtocolViolationException: You must write ContentLength bytes to the request stream before calling [Begin]GetResponse.
at System.Net.HttpWebRequest.GetResponse()
....
....
My GET requests for other URL end points are working fine, I am only having this issue while issuing a POST request. Also, I have already set the ContentLength in the code appropriately. I am still unable to send the POST request. Thoughts?
public void TestSubmitJobWithParams1()
{
const string RestActionPath = "URL_GOES_HERE";
// if you have multipe parameters seperate them with teh '&' delimeter.
var postData = HttpUtility.UrlEncode("MaxNumberOfRowsPerSFSTask") + "=" + HttpUtility.UrlEncode("3000");
var request = (HttpWebRequest)WebRequest.Create(RestActionPath);
request.Method = "POST";
request.Credentials = CredentialCache.DefaultCredentials;
request.PreAuthenticate = true;
request.ContentLength = 0;
request.Timeout = 150000;
request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
request.ContentType = "application/x-www-form-urlencoded";
byte[] bytes = Encoding.ASCII.GetBytes(postData);
request.ContentLength = bytes.Length;
Stream newStream = request.GetRequestStream();
newStream.Write(bytes, 0, bytes.Length);
string output = string.Empty;
try
{
using (var response = request.GetResponse())
{
using (var stream = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(1252)))
{
output = stream.ReadToEnd();
}
}
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError)
{
using (var stream = new StreamReader(ex.Response.GetResponseStream()))
{
output = stream.ReadToEnd();
}
}
else if (ex.Status == WebExceptionStatus.Timeout)
{
output = "Request timeout is expired.";
}
}
catch (ProtocolViolationException e)
{
Console.WriteLine(e);
}
Console.WriteLine(output);
Console.ReadLine();
}
A few things:
Firstly, you don't need to set ContentLength directly - just leave it out (defaults to -1). You're actually calling it twice, so remove both calls.
Also, you need to call Close() on the stream before calling GetResponse()
Stream newStream = request.GetRequestStream();
newStream.Write(bytes, 0, bytes.Length);
newStream.Close();
Alternatively, you could have it within a using statement, which handles the closing and disposal for you):
using (var newStream = request.GetRequestStream())
{
newStream.Write(bytes, 0, bytes.Length);
}
You also don't technically need to use HttpUtility.UrlEncode() for the postData since there's nothing in your string that would violate a Url's integrity. Just do:
string postData = "MaxNumberOfRowsPerSFSTask=3000");
Let me know if that solves it for you.
For a more thorough rundown, check this out: http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.getresponse.aspx
Specifically, the section about ProtocolViolationException and also where it says:
When using the POST method, you must get the request stream, write the data to be posted, and close the stream. This method blocks waiting for content to post; if there is no time-out set and you do not provide content, the calling thread blocks indefinitely.

Win Phone7 WebRequest Not returning on first call

I am creating an app that will talk to a HTTP Listener service.
I have taken code from this Posting Posting with HttpWebRequest on Windows Phone 7
This code seems to work almost perfectly, it just doesn't work on the very first call.
The call is making it to the service and is not throwing an error. Just the return value is empty.
On the second call, I am getting the return value without problem. If I go to another page and back again, I also get the return value first time. This is only happening on the first call when the app is first started.
Any ideas would be greatly appreciated. Code Below.
SERVICE
DiagnosticLog.Write(99, DateTime.Now, "Phone Listener Called");
IAsyncResult phoneResult = PhoneListener.BeginGetContext(new AsyncCallback(Phone), PhoneListener);
HttpListenerContext context = null;
HttpListenerResponse response = null;
HttpListener _listener = (HttpListener)result.AsyncState;
context = _listener.EndGetContext(result);
HttpListenerRequest request = context.Request;
response = context.Response;
//response.ContentType = "text/plain";
string postData = string.Empty;
using (StreamReader sr = new StreamReader(request.InputStream))
{
DiagnosticLog.Write(99, DateTime.Now, "Reading Stream");
postData = sr.ReadToEnd();
}
byte[] buffer;
System.IO.Stream output = response.OutputStream;
if (postData == "islogin")
{
buffer = System.Text.Encoding.UTF8.GetBytes("logincorrect");
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
DiagnosticLog.Write(99, DateTime.Now, "Good Return sent");
output.Close();
}
else
{
buffer = System.Text.Encoding.UTF8.GetBytes("loginincorrect");
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
DiagnosticLog.Write(99, DateTime.Now, "Bad Return sent");
output.Close();
}
CODE (phone app)
WebRequest request = WebRequest.Create("http://127.0.0.1:8080/phone");
request.Method = "POST";
request.BeginGetRequestStream(ar =>
{
var requestStream = request.EndGetRequestStream(ar);
using (StreamWriter sw = new StreamWriter(requestStream))
{
sw.Write("islogin");
}
request.BeginGetResponse(a =>
{
try
{
WebResponse response = request.EndGetResponse(a);
Stream responseStream = response.GetResponseStream();
using(var sr = new StreamReader(responseStream))
{
Storage.ReturnValue = sr.ReadToEnd().ToString();
}
}
catch(WebException ex)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(ex.ToString());
});
}
}, null);
}, null);
txtLoginUsername.Text = Storage.ReturnValue;
The answer is that the phone continues, so when the page updates, there is still no data present.

Categories

Resources