Code Outside of the Box

« Improving Async Support in ASP.NET MVC - Part 3 - Async Filter API

Hydrogen Extensions for ASP.NET MVC 5 Alpha Release

First published on March 20, 2017

I’m happy to share the first alpha release of my extensions library for ASP.NET MVC 5 which adds support for async filters.

You can download the library from NuGet and the source is available on GitHub.

You can read about my journey to get here:

Getting started

First we need to swap out the default implementation IAsyncActionInvoker with Hydrogen.Extensions.Mvc5.Async.ControllerActionInvokerEx. There are two ways to do this:

1) Set the ActionInvoker property of a controller when it’s constructed:

public class HomeController : Controller
{
    public HomeController()
    {
        ActionInvoker = ControllerActionInvokerEx.Instance;
    }
}

2) Using your DI container of choice, register Hydrogen.Extensions.Mvc5.Async.ControllerActionInvokerEx as an implementation of IAsyncActionInvoker.

For example (using Autofac):

builder.RegisterInstance(ControllerActionInvokerEx.Instance)
        .As<IAsyncActionInvoker>()
        .SingleInstance();

Note that ControllerActionInvokerEx can be used as a singleton. It doesn’t maintain any state.

Creating an async filter

You may create a subclass of AsyncActionFilterAttribute or AsyncExceptionFilterAttribute and override the async methods.

For example:

public class MyAsyncActionFilterAttribute : AsyncActionFilterAttribute
{
    public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        // Execute code before the action is invoked.
        // You can "short-circuit" the action by setting 'context.Result'
        // and returning before calling 'next()'.
        
        // The implementation is responsible for calling 'next()'.
        var actionExecutedContext = await next().ConfigureAwait(false);

        // Execute code after the action is invoked
    }

    public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
    {
        // Execute code before the result is invoked.
        // You can "short-circuit" the action by setting 'context.Canceled = true'
        // and returning before calling 'next()'.
        
        // The implementation is responsible for calling 'next()'.
        var resultExecutedContext = await next().ConfigureAwait(false);

        // Execute code after the result is invoked
    }
}

Alternately you may implement any of the async filters:

Unfortunately, for compatibility reasons, you must also implement the non-async version of these filters (e.g. void OnActionExecuting(ActionExecutingContext filterContext)). However, these methods can be a NOOP since the code is never executed by ControllerActionInvokerEx.

This library, currently, does not implement as async version of IAuthenticationFilter.

This is an alpha release

I fully expect there to be bugs, however I hope to use it in real production code soon.

Maybe one day this code, or some derivation there of, can make it into an official release.

I hope someone else might find this library useful. And I’d appreciate feedback, comments, or contributions (including bug reports)!

Comments

Comments are not moderated. But I reserve the right to delete anything hostile, offensive, or SPAMy.