Reputation: 4274
I'm working on a proof of concept prototype.
I have Asp.Net C# web form (Visual Studio 2013, .Net 4.5) page. On a button click I do something like this:
List<Blog> blogs = null;
protected void btnLoadData_Click(object sender, EventArgs e)
{
//...;
switch (int.Parse(rblDataSource.SelectedValue))
{
//...;
case 4:
RunAsyncBlogs().Wait();
break;
default:
blogs = localGetter.GetBlogs();
break;
}
//...;
}
RunAsyncBlogs looks like this:
static async Task RunAsyncBlogs()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost/wapiDemo/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP GET
HttpResponseMessage response = await client.GetAsync("api/Blogs");
if (response.IsSuccessStatusCode)
{
List<Blog> thisBlogList = await response.Content.ReadAsAsync<List<Blog>>();
var cnt = thisBlogList.Count();
}
}
}
The code stops at the response = await client.GetAsync call. When I say it stops, the debugger acts like the request has ended, but the browser is still waiting.
If I run a console app (I copy and paste the RunAsync() method into it) which calls the Web API the same way, I get my data. So, I believe the Web API app is responding as expected.
Upvotes: 5
Views: 15006
Reputation: 1
Is a Web Application with VS2013 with WEbAPi and MVC In MVC I have I link to this:
public JsonResult GetWithHttpClient()
{
Employee employee = null;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(path);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("api/Employees/12345").Result;
//the IsSuccessStatusCode property is false if the status is an error code.
//All the error: {StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:{ Pragma: no-cache X-SourceFiles: =?UTF-8?B?QzpcRkFCSU9fQ09ESUNFXE15RXhhbXBsZVxXZWJBcHBsaWNhdGlvbjFcV2ViQXBwbGljYXRpb24xXGFwaVxFbXBsb3llZXNcMTIzNDU=?= Cache-Control: no-cache Date: Tue, 28 Jul 2015 14:47:03 GMT Server: Microsoft-IIS/8.0 WWW-Authenticate: Bearer X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Content-Length: 61 Content-Type: application/json; charset=utf-8 Expires: -1}}
if (response.IsSuccessStatusCode)
{
employee = response.Content.ReadAsAsync<Employee>().Result;
}
}
return Json (employee, JsonRequestBehavior.AllowGet);
}
The WebApi is called EmployeesController. And I have this method:
public Employee Get(int id)
{
return list.First(e => e.Id == id);
}
Upvotes: 0
Reputation: 26687
Problem is that you have to nested async
methods. RunAsyncBlogs
and response.Content.ReadAsAsync<List<Blog>>();
inside of it.
Adding .ConfigureAwait(false)
at the end of following line will prevent your code from hanging:
var thisBlogList = await response.Content.ReadAsAsync<List<Blog>>().ConfigureAwait(false);
However, even though this will solve blocking, code will still execute synchronously, because of the Wait()
call in btnLoadData_Click
method.
Switching to asynchronous execution, as already suggested is better solution.
Upvotes: 1
Reputation: 5312
Your button click event needs to be async.
protected async void btnLoadData_Click(object sender, EventArgs e)
{
//...;
switch (int.Parse(rblDataSource.SelectedValue))
{
//...;
case 4:
await RunAsyncBlogs();
break;
default:
blogs = localGetter.GetBlogs();
break;
}
//...;
}
See this post on dealing with blocking issues with async.
http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
Upvotes: 0
Reputation: 149558
This:
RunAsyncBlogs().Wait();
Is deadlocking your code. It is synchronously blocking your async method call which is trying to marshal back the continuation on to the implicitly captured synchronization context. That is why you shouldn't block on async code
protected async void btnLoadData_Click(object sender, EventArgs e)
{
// Other stuff
await RunAsyncBlogs();
}
Upvotes: 4