When I try the following code:
var request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Timeout = 3; // a small value
var response = request.GetResponse();
Console.WriteLine(response.ContentLength);
for a URL that I know it is going to take more than 3 millisecond to load (I put a Thread.Sleep(110000) in Application_BeginRequest) it works fine and throws a WebException as expected.
Problem is when I switch to async method:
var response = request.GetResponseAsync().Result;
or
var response = await request.GetResponseAsync();
This async version completely ignores any Timeout value, including ReadWriteTimeout and ServicePoint.MaxIdleTime
I couldn't find anything about Timeout in MSDN's GetResponseAsync() now I'm wondering if it is a bug in GetResponseAsync() or something is wrong in the way I use async here?
Timeout does not apply to asynchronous HttpWebRequest requests. To quote the docs:
The Timeout property has no effect on asynchronous requests
I recommend you use HttpClient instead, which was designed with asynchronous requests in mind.
Follow a solution to solve the problem.
await Task.Run(() => {
var varHttpResponse = varWebRequest.GetResponse();
});
Related
I am developing a WPF application where I am consuming some HTTP API to get data, I am using System.Net.Http.HttpClient class to make API calls, but as soon I call GetAsync method of the client I don't get any response back from the API and the debugger just goes away.
Below is the line I am using to make the call where the debugger gets lost
var response = await client.GetAsync(endpoint);
I don't know why I am not getting any response from the API.
Note: The API is working on browser as it is a simple GET call.
Try following
var response = await client.GetAsync(endpoint).ConfigureAwait(false);
Making the HTTP call inside Task.Run worked for me, I assume that this has something to relate with UI Thread blocking.
Thanks everyone for the help!!
var task = Task.Run(() => {
var response = await client.GetAsync(endpoint);
});
await task;
The documentation about the PostAsync method of the HttpClient is a bit...on the low side.
I'm wondering about the behaviour of it:
Does it bring any exceptions in case of timeout or when the Website called throws an exception? If not what happens in These cases?
As example
using (HttpClient Client = new HttpClient())
{
var result = Client.PostAsync(url, content).Result;
}
The site called sometime throws exceptions or in the case of high traffic times out. I'm not sure what the result is then. Do I get exceptions, "endless Loop" (thus timeouts don't occur), or is just the result empty if exceptions are thrown or a timeout occurs?
As a first note, please avoid using Result. It is a blocking call. You should use the async/await keywords. Mark the corresponding method as async and prepend the method call with await:
var result = await Client.PostAsync(url, content);
Regarding your question, the result of this call is a Task<HttpResponseMessage>.
Statuses of a Tasks can be found here TaskStatus Enumeration. Of course this call can fail. So you should catch any exception that may be thrown.
I'd like to see what the request body of my HTTP request contained for debugging purposes. Here's what I've got right now:
var httpResponseMessage = await _httpClient.PostAsync(uri, objectToInsert, jsonFormatter);
//This throws an exception
var thisDoesntWork = await httpResponseMessage.RequestMessage.Content.ReadAsStringAsync();
This throws an ObjectDisposedException. How can I view the request body to make sure the JSON being sent is correct?
The short answer is you can't after the request has already been sent. HttpClient disposes the content body after the request is made as a convenience to the developer. See Why do HttpClient.PostAsync and PutAsync dispose the content? for some detail.
As an alternative, you could inherit from an existing HttpContent implementation, override the Dispose method, and log the body of the content prior to disposal.
Or, as suggested, use an external tool to monitor the request in flight.
You'd need to first create a HttpRequestMessage to pass to the HttpClient. Then you can just evaluate/log the content.
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
request.Content=JsonSerializer.Serialize(objectToInsert);
Console.WriteLine(request.Content.ReadAsStringAsync().Result);
HttpResponseMessage response = await httpClient.SendAsync(request);
ObjectDisposedException is thrown because you're disposing the HttpRequestMessage and HttpClient before Content.ReadAsStringAsync() finishes.
Note that Content.ReadAsStringAsync() is an asynchronous method. You need to wait for it to complete before disposing the HttpClient.
If you are not wanting to use async you can add .Result to force the code to execute synchronously:
var response = httpClient.PostAsync(BaseUri, new FormUrlEncodedContent(parameters)).Result;
var contents = response.Content.ReadAsStringAsync().Result;
There are multiple URLs,I use asynchronous request to call the URLs,but most requests are timed out.The URLs are accessible,asynchronous request only any one of the URLs, can get a response.The code like this:
foreach (var url in URLs)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
IAsyncResult result = (IAsyncResult)request.BeginGetResponse(new AsyncCallback(RequestCallback), request);
ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request, request.Timeout, true);
}
Can someone tell me the reason?
Not exactly an answer, but if you have .net 4.5 and VS2012 you can use async await, which is much cleaner. The code would be...
var tasks = from url in URLs
let request = WebRequest.Create(url)
select request.GetRequestStreamAsync();
Stream[] results = Task.WaitAll(tasks);
However this isn't a very good way to write code. You should process your streams as quickly as possible, as Windows should limit the number of Http streams your program can have open at the same time.
In this walkthrough:
http://msdn.microsoft.com/en-us/library/vstudio/hh300224.aspx
how would the asynchronous approach be modified to handle timeout scenarios?
using (WebResponse response = await req.GetResponseAsync())
{
}
Or would a different approach have to be taken?
The easiest way to do async HTTP requests is to use HttpClient rather than WebRequest, and HttpClient has a Timeout property you can set.
Set the Timeout property on the WebRequest object
Follow a solution to respect the timeout
await Task.Run(() => {
var varHttpResponse = varWebRequest.GetResponse();
});