20

The problem

I have an api GET method to retrieve site configuration. I am using httpClient and the GetAsync() method to do this.

HttpResponseMessage response = await client.GetAsync("api/{0}/config", id);

As I need this configuration across the site, I planned to use a global action filter for this.

Question

How can I call an async method in an MVC action filter? Or is there a better solution to this problem?

I have looked at multiple SO questions (Async action filter in MVC 4) on this but I not found a satisfactory solution.

Community
  • 1
  • 1
Colin Bacon
  • 15,436
  • 7
  • 52
  • 72

1 Answers1

26

There is no way to (reliably) call an asynchronous method from an ASP.NET MVC 5 action filter. This has already been fixed in ASP.NET vNext, but AFAIK there are no plans to support this in MVC 5.

If you absolutely must do this in an action filter, then you must use synchronous calls (e.g., WebClient instead of HttpClient).

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • 2
    Thanks. Would you advise against doing something like this `Task.Run(() => GetSomethingAsync(id)).Result;` in the action filter. If so could you explain the reasons why. – Colin Bacon Jan 19 '15 at 18:15
  • 3
    @ColinBacon: There are [a few hacks](http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx) you can use to try to force "sync over async", but every one has drawbacks. `Task.Run` will interfere with the ASP.NET thread pool heuristics, negatively impacting scalability. Also, `Task.Run` will explicitly run `GetSomethingAsync` *outside* the current ASP.NET request context - whether or not this will work depends on what exactly `GetSomethingAsync` tries to do. So in short, it may work (with a small performance hit), or it may not - depends on your method's implementation. – Stephen Cleary Jan 19 '15 at 18:21
  • 10
    I can confirm the negative impact on scalability. We have quite a large site running in production on Azure and I was doing this exact thing: `Task.Run(() => DoSomethingAsync).Wait()` in an action filter. On heavy load this resulted in terrible performance. Requests were added to the request queue as threads were exhausted. CPU was low so no instance would be added as the async work was calling a 3rd party service. We ended up with response times of +100 seconds. Do NOT do this :-) – Razzie Jun 21 '15 at 05:17