I'm having a problem with an async method that I implemented. The method basically makes a HttpRequest to a resource and deserializes the string if the request is successful. I wrote a test for the method, and it works. But the method does never return when I call it from a controller?
public async Task<IEnumerable<T>> Get()
{
try
{
var resourceSegmentUri = new Uri(_uri, UriKind.Relative);
var response = await _client.GetAsync(resourceSegmentUri);
if (response.IsSuccessStatusCode)
{
var submission = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<IEnumerable<T>>(submission);
}
if (response.Content != null)
{
var message = response.Content.ReadAsStringAsync();
throw new WebException(message.Result, (WebExceptionStatus)response.StatusCode);
}
}
catch (WebException e)
{
Logger.Error("GET Request failed with status: {0}", e.Status);
throw;
}
throw new Exception();
}
Code that never returns:
public ActionResult Index()
{
var api = new Api();
var test = api.Get().Result; //Never returns
return View();
}
Test that works:
[Test]
public void GetShouldReturnIfSuccessfulRequest()
{
var api = new Api();
var submission = api.Get();
Console.WriteLine(JsonConvert.SerializeObject(submission));
Assert.NotNull(submission);
}
Does anyone know the problem?
The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.
Async methods can have the following return types: Task, for an async method that performs an operation but returns no value. Task<TResult>, for an async method that returns a value. void , for an event handler.
The return type of Task<ActionResult> represents ongoing work and provides callers of the method with a handle through which to wait for the asynchronous operation's completion. In this case, the caller is the web service. Task<ActionResult> represents ongoing work with a result of ActionResult.
You've got a deadlock because you're calling .Result
in your controller action.
If you use async/await
then you have to use asynchronous actions too.
So something like this should fix it:
public async Task<ActionResult> Index()
{
var api = new Api();
var test = await api.Get(); // Should return
}
There's a comprehensive article about this here: Using Asynchronous Methods in ASP.NET MVC 4
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With