Is there a way to use restsharp synchronously? Every method I see in Visual Studio has the "async" postfix and the restsharp main page, (which has the following example):
// execute the request
RestResponse response = client.Execute(request);
var content = response.Content; // raw content as string
Clearly makes the distinction between sync and async requests:
// easy async support
client.ExecuteAsync(request, response => {
Console.WriteLine(response.Content);
});
How can I access this "Execute" sync method?
I asked in their googlegroups and they said that it is because of "platorm limitations" when using wp7. Pretty neat right?
Related
I used quote marks around "right way" because I'm already well aware that the right way to use an asynchronous API is to simply let the asynchronous behavior propagate throughout the entire call chain. That's not an option here.
I'm dealing with a very large and complicated system designed specifically to do batch processing synchronously in a loop.
The reason why suddenly I'm using HttpClient is because prior to now all data for the batch processing was gathered from a SQL database, and now we're adding a Web API call to the mix.
Yes, we're calling a Web API in a synchronously executing loop. I know. Rewriting the whole thing to be async just isn't an option. This is actually what we want to do. (We're minimizing the number of API calls as much as possible)
I actually did try to propagate the async behavior up the call chain, but then I found myself 50 files deep in changes, still with hundreds of compiler errors to resolve, and lost all hope. I am defeated.
So then, back to the question, given Microsoft's recommendation to never use WebRequest for new development and to instead use HttpClient, which offers only an asynchronous API, what am I to do?
Here is some pseudo-code of what I'm doing...
foreach (var thingToProcess in thingsToProcess)
{
thingToProcess.ProcessStuff(); // This makes an API call
}
How do I implement ProcessStuff()?
My first implementation looked like this
public void ProcessStuff()
{
var apiResponse = myHttpClient // this is an instance of HttpClient
.GetAsync(someUrl)
.Result;
// do some stuff with the apiResponse
}
I was told however, that calling .Result in this manner can result in deadlocks when it's called from something like ASP.NET due to the synchronization context.
Guess what, this batch process will be kicked off from an ASP.NET controller. Yes, again, I know, this is silly. When it runs from ASP.NET it's only "batch processing" one item instead of the whole batch, but I digress, it still gets called from ASP.NET and thus I'm concerned about deadlocks.
So what's the "right way" to handle this?
Try the following:
var task = Task.Run(() => myHttpClient.GetAsync(someUrl));
task.Wait();
var response = task.Result;
Use it only when you cannot use an async method.
This method is completely deadlock free as mentioned on the MSDN blog:
ASP.Net–Do not use Task .Result in main context.
For anyone coming across this now, .NET 5.0 has added a synchronous Send method to HttpClient. https://github.com/dotnet/runtime/pull/34948
You can therefore use this instead of SendAsync. For example
public string GetValue()
{
var client = new HttpClient();
var webRequest = new HttpRequestMessage(HttpMethod.Post, "http://your-api.com")
{
Content = new StringContent("{ 'some': 'value' }", Encoding.UTF8, "application/json")
};
var response = client.Send(webRequest);
using var reader = new StreamReader(response.Content.ReadAsStream());
return reader.ReadToEnd();
}
This code is just a simplified example, it's not production ready.
You could also look at using Nito.AsyncEx, which is a nuget package. I've heard of issues with using Task.Run() and this this addresses that. Here's a link to the api docs:
http://dotnetapis.com/pkg/Nito.AsyncEx/4.0.1/net45/doc/Nito.AsyncEx.AsyncContext
And here's an example for using an async method in a console app:
https://blog.stephencleary.com/2012/02/async-console-programs.html
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;
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;
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();
});
I am trying to conduct an HTTP call to another server from within an ASP.NET application run on IIS 8.5.
To get started, I took some hints from an article by Microsoft, Call a Web API From a .NET Client (C#).
I could easily see a pattern of how they make HTTP calls there; to show just one shortened example:
static async Task<Product> GetProductAsync(string path)
{
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
// retrieve response payload
... = await response.Content.ReadAsAsync<...>();
}
// do something with data
}
Easy enough, I thought, so I quickly wrote a similar method for my application (note that the ReadAsAsync extension method appears to require an additional library, so I chose one of the built-in, more abstract, but otherwise presumeably analogous methods):
private async Task<MyInfo> RetrieveMyInfoAsync(String url)
{
var response = await HttpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<MyInfo>(responseBody);
}
Unfortunately, calling this method will cause my application to hang. When debugging, it turns out that the await call to GetAsync never returns.
After searching around for a bit, I stumbled over a remotely similar issue, in whose comments section I found a very interesting suggestion by Mr. B:
Remove all the async stuff and make sure it works.
So I gave it a try:
private Task<MyInfo> RetrieveMyInfoAsync(String url)
{
return HttpClient.GetAsync(url).ContinueWith(response =>
{
response.Result.EnsureSuccessStatusCode();
return response.Result.Content.ReadAsStringAsync();
}).ContinueWith(str => JsonConvert.DeserializeObject<MyInfo>(str.Result.Result));
}
Somewhat surprisingly (to me), this works. GetAsync returns the expected response from the other server within less than a second.
Now, working with AngularJS at the same time, I am a bit disappointed by things like response.Result.Content and str.Result.Result. In AngularJS, I'd expect the above call to be simply something like:
$http.get(url).then(function (response) {
return response.data;
});
Even if we discount the automatic JSON deserialization that's happening in JavaScript, the AngularJS code is still easier as e.g. response is not wrapped into a promise or anything like that, nor will I end up with a structure like Task<Task<...>> when returning another promise from within the continuation function.
Therefore, I am not very happy with having to use this ContinuesWith syntax rather than the more readable async-await pattern, if the latter just worked.
What am I doing wrong in the async-await variant of my C# HTTP call?
So judging by the fact that ConfigureAwait(false) helped with your issue, please, read these from Stephen Cleary's blog:
http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
The guy's pretty much an async expert (he wrote the Concurrency in C# Cookbook book), so whatever I can say he probably explains better. Basically you're blocking the ASP.NET thread somewhere, maybe not using await all the way but rather Wait, Result or GetResult(). You should be able to diagnoze the issue yourself using that blog.
What ConfigureAwait(false) does is it does not capture the current context, so the HTTP request gets performed (correctly) somewhere else than on the ASP.NET context, preventing a deadlock.
EDIT:
GetAwaiter().GetResult() is what's causing the issue, judging by your comment. If you changed that to await and the calling method to async you'd probably fix everything.
Since C# 7.0 and async Task Main() method support there's really no reason to block instead of using await in your application code, ever.