HttpWebRequest.GetRequestStream : What it does? - c#

Code exemple:
HttpWebRequest request =
(HttpWebRequest)HttpWebRequest.Create("http://some.existing.url");
request.Method = "POST";
request.ContentType = "text/xml";
Byte[] documentBytes = GetDocumentBytes ();
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(documentBytes, 0, documentBytes.Length);
requestStream.Flush();
requestStream.Close();
}
When I do request.GetRequestStream (), there's nothing to send in the request. From the name of the method, and the intellisense it shows ("Get System.IO.Stream to use to write request data"), nothing indicates that this line of code will connect to the distant server.
But it seems it does...
Can anyone explain to me what HttpWebRequest.GetRequestStream () exactly does ?
Thanks for your enlightenments.

Getting the request stream does not trigger the post, but closing the stream does. Post data is sent to the server in the following way:
A connection is opened to the host
Send request and headers
Write Post data
Wait for a response.
The act of flushing and closing the stream is the final step, and once the input stream is closed (i.e. the client has sent what it needs to the server), then the server can return a response.

You use GetRequestStream() to synchronously obtain a reference to the upload stream. It is only after you have finished writing to the stream that the actual request is send.
However, I would suggest that you use the BeginGetRequestStream method instead of GetRequestStream. BeginGetRequestStream performs asynchronously and don't lock the current thread while the stream is being obtained. You pass a callback and a context to the BeginGetRequestStream. In the callback, you can call EndGetRequestStream() to finally grab a reference and repeat the writing steps listed above (for synchronous behavior). Example:
context.Request.BeginGetRequestStream(new AsyncCallback(Foo), context);
public void Foo(IAsyncResult asyncResult)
{
Context context = (Context)asyncResult.AsyncState;
try
{
HttpWebRequest request = context.Request;
using (var requestStream = request.EndGetRequestStream(asyncResult))
using (var writer = new StreamWriter(requestStream))
{
// write to the request stream
}
request.BeginGetResponse(new AsyncCallback(ProcessResponse), context);
}
Be very careful with BeginGetRequestStream. It never times out, thus you must add additional logic to your program to recover from situations where GetRequestStream will throw a timeout exception.
In general, threads are cheap. The async Begin/End methods of HttpWebRequest are only worth using if you will have 10,000 or more concurrent requests; because implementing timeouts is very tricky and error-prone. In general, using BeginGetRequestStream is premature optimization unless you need significant performance gains.

Related

WebRequest - GetRequestStream timing out with exception

I'm writing this short module where I have to modify an addressed resource with a PUT method. I'm using the WebRequest class to make this URI request and the GetRequestStream() to get the stream to write to.
However, it seems that after a couple of successful method calls (and using the PUT to modify resources) via this method below, my application hangs and then throws a WebException: The request timed out. error. Here's what the code looks like:
public void SendOffMessageToResource(int res_ID){
var httpWebRequest = WebRequest.Create ("http://192.168.x.x/api/sample_user/resources/1/state");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "PUT";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) //here's where the VS seems to take a long long time to step over to the next line when the error happens.
{
string json = "{\"on\":false}";
streamWriter.Write(json);
streamWriter.Close();
}
}
I am already disposing the StreamWriter. I'm not even using the GetResponse() method, because all I need to do on this URI is actually modify the addressed resource with PUT method. I am not sure why it still throws an error and hangs the application. The search of previous threads only revealed that people should be using using statements to dispose resources, but I'm already doing that I think or perhaps I'm missing something? Do I always need to use GetResponse() to complete the request and dispose that always in addition to this?
Do I always need to use GetResponse() to complete the request and dispose that always in addition to this?
Yes, just that.

jQuery POST to a .NET HttpListener and back again

I have a chunk of javascript code that uses jQuery.post to send some data to a .NET app that's using an HttpListener.
Here's the js:
$.post("http://localhost:8080/catch", { name: "John", time: "2pm" },
function(data) {
alert(data);
});
and the C#:
HttpListenerContext context = listener.GetContext();
HttpListenerRequest request = context.Request;
StreamReader reader = new StreamReader(request.InputStream);
string s2 = reader.ReadToEnd();
Console.WriteLine("Data received:" + s2);
// Obtain a response object.
HttpListenerResponse response = context.Response;
// Construct a response.
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
The post request goes out ok, and the .NET app reads in the data ok, but the JS code doesn't seem to get the response. The callback function to the jQuery.post fires, but data is always undefined.For brevity I have omitted some C# above where I set the prefixes to the listener.
Any ideas why I'm not getting my data back client-side?
EDIT: I should add that when I run the JS with HttpFox running I get Http code 200, 'NS_ERROR_DOM_BAD_URI', which I thought had something to do with the "http://localhost:8080/catch" I was targeting, but when I hit that resource in firefox, i get the HTML response just fine and it registers as a GET, 200.
EDIT: I simplified the response to just 'meow', and this is what fiddler is giving me for the full response:
HTTP/1.1 200 OK
Content-Length: 4
Content-Type: text/html
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 15 Apr 2011 12:58:49 GMT
meow
Don't forget about the same origin policy restriction. Unless your javascript is hosted on http://localhost:8080 you won't to be able to send AJAX requests to this URL. A different port number is not allowed either. You will need to host your javascript file on an HTML page served from http://localhost:8080 if you want this to work. Or have your server send JSONP but this works only with GET requests.
Remark: make sure you properly dispose disposable resource on your server by wrapping them in using statements or your server might start leaking network connection handles.
Don't forget to release the resources by closing the response.
Calling Close on the response will force the response to be sent through the underlying socket and will then Dispose all of its disposable objects.
In your example, the Close method is only called on the Output stream. This will send the response through the socket, but will not dispose any resources related to the response, which includes the output stream you referenced.
// Complete async GetContext and reference required objects
HttpListenerContext Context = Listener.EndGetContext(Result);
HttpListenerRequest Request = Context.Request;
HttpListenerResponse Response = Context.Response;
// Process the incoming request here
// Complete the request and release it's resources by call the Close method
Response.Close();
I do not see setting of content-type. Set the content-type to text/html.
response.ContentType = "text/html";
You can simplify the writing code a lot. Just use this:
// Construct a response.
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
context.Response.Write(responseString);
No need for the OutputStream or most of that other code. If you do have a reason to use it, note that you actually should not close the OutputStream. When you use Resopnse.OutputStream you're retrieving a reference to it but you're not taking ownership. It's still owned by the Response object and will be closed properly when the Response is disposed at the end of the request.

HttpWebRequest and Response for reading large streams

I have a requirement where I need to read large stream or data from a web server.
This is not streaming but reading large data in chunks from the client side.
For this purpose I create an Http Web Request. Following is the sample code..
StreamingObject streamObj = null;
using (HttpWebRequest httpReq = WebRequest.Create(uri))
{
HttpWebResponse response = httpReq.GetRespons();
Stream responseStream = response.GetStream();
streamObj = new StreamingObject(response, responseStream);
}
return streamObj;
In my code I make a Http Web request to given Uri. Then I get the HttpWebResponse and the Response Stream. Create an instance of StreamingObject which is a wrapper class for storing the Http response and the response stream.
I have disposed the Http Web Request. The client is provided with the StreamingObject and the streaming object has one method GetStream which returns the underlying response stream. When the StreamingObject is disposed the Http response and the stream is disposed.
The reason for introducing the StreamingObject was that the Http Response has to be kept open for accessing the underlying stream.
I wish to know whether this is a correct approach or there is simpler way of doing.
I would suggest not disposing of the HttpWebRequest object, because you might very well need it. Just add it to StreamingObject and dispose of it when you dispose of the StreamingObject. For example, I've found that if I want to close the response stream prematurely, the response will hang until all of the data has been read. But calling Abort on the request object will immediately close the stream.

web request timeout handling?

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Timeout = 20000;
using (WebResponse response = request.GetResponse())
using (var stream = response.GetResponseStream())
using (var reader = new StreamReader(stream))
{
var result = reader.ReadToEnd();
// Do something with result
}
In the above example I have a timeout defined, if it happens to hit the timeout how would I know, the result would be empty ?
Do I receive any reponse types ?
How can I make sure I got timed out ?
GetResponse() would throw a WebException. It's simple to test exactly what happens though - set the timeout to 1ms and try to hit anything which takes a while to come back.
In fact, the documentation states this explicitly:
If the timeout period expires before the resource can be returned, a WebException is thrown.
Your HttpWebRequest.GetResponse call will throw a WebException when;
Abort was previously called.
-or-
The time-out period for the request expired.
-or-
An error occurred while processing the request.
Catch this exception.
I used to just pull my network cable out to test this sort of thing although you could be more elegant and use a proxy tool and block that particular request.
You should probably be using HTTPWebResponse. It has a status code that tells you that information and more. HTTPWebResponse is a descendant of WebResponse.

How to force IIS to send response headers without sending response body and closing connection

I am trying to stream dynamically generated data to a client over HTTP using IIS, and the connection has to remain open for a long period of time, and the server will send periodic status updates to the client while it is performing a time-consuming operation.
This MUST all be handled within ONE request, but I am using a WebClient.OpenRead() stream, which cannot be opened until the headers are sent.
How can I force IIS to send headers to the client, and later send a response body?
This behaviour is normally achievable by setting KeepAlive to true and setting Expect header to "100 and continue". By doing this, server will send the headers with result code 100.
I am not sure if this is possible using WebClient.
Use HttpWebRequest instead to be able to set the values above. In fact WebClient does nothing magical but using GET to get the data. Here is the code for calling OpenRead in Reflector:
try
{
request = this.m_WebRequest = this.GetWebRequest(this.GetUri(address));
Stream responseStream = (this.m_WebResponse = this.GetWebResponse(request)).GetResponseStream();
if (Logging.On)
{
Logging.Exit(Logging.Web, this, "OpenRead", responseStream);
}
stream2 = responseStream;
}
catch (Exception exception)
{
//

Categories