Asynchronous action filters in ASP.NET Web API - StrathWeb

Strath

November 24th, 2013

Asynchronous action filters in ASP.NET Web API

It is rather to common to use filters in Web API to perform common tasks around your actions in an AOP (aspect oriented programming) way.

To create a filter you simply inherit from an abstract ActionFilterAttribute class and override the relevant method:

This is all nice and simple, but what if the operation you need to perform, should by asynchronous? Surely async void is a terrible idea.

Avoiding the async void issue

So if you read the linked article about the async void it’s quite clear we cannot use that approach.

However, there is nothing that forces you to create filters by inheriting from ActionFilterAttribute – instead you can implement IActionFilter manually.

That one is completely asynchronous:

ActionFilterAttribute simply wraps around this interface and hides (!) its asynchronous nature, only exposing the void virtual hooks.

Another point worth mentioning, is that – as you have probably already noticed – the interface doesn’t have pre- and post- action hooks but rather a single method and a continuation.

This means that to perform an activity before action executes, we do it straight away, and to perform an activity after the execution, we have to await the continuation and perform our activity afterwards.

Implementing IActionFilter

To illustrate all this best, let’s start the implementation:

So what we did here is we have added two methods returning Task representing our pre/post processing hooks (I marked them public virtual so that the filter can be reused, but you might as well use privates if that suits you). The methods return Task so they can be async and await for stuff internally.

Then in the actual interface implementing method we await for the pre-processing hook, and if it sets a response (a.k.a. a “short-circuited” response), we return it. Otherwise, we await the continuation (which is the actual action executing) and continue with the post processing hook (we have to create HttpActionExecutedContext manually).

It’s all pretty simple and quite easy to implement by hand and as a result we have fully fledged support for async filters in our Web API.

Why isn’t this part of the core framework?

You might ask, why do you have to jump through these hoops to have async filter. It clearly seems to be an oversight in the framework code.

Fortunately, the team has already addressed that and in the next upgrade to Web API, async filters will be supported out of the box, and the new ActionFilterAttribute will have two additional methods to override (this is actually already available in the nightly builds):

Until that upgrade, you can use the workaround shown here.

Be Sociable, Share!