Injecting all the WebAPI Things

Dependency Injection is all the rage and has become a must for just about any application, in particular if you are using Entity Framework as it allows for each Request level DbContext instance management. Let me explain.

Think of the DbContext as a pipe into the database. I often see code like this in applications I review for West Monroe:

using (var context = new SomeContext())
{
    // some data access code here
}

This is bad because each time you use this you create another pipe into your database. And if your code is complex it may contain multiple calls to service which open a context each time. This can quickly overwhelm the database as it can drain the connection pool and create performance problems.

The reason Dependency Injection helps with this is it allows us to inject instances at varying levels of scope. And in the case of the web the most ideal scope level is the Request.

The present gold standard for DI (Dependency Injection) is the AutoFac library. It is easily downloadable from Nuget and integrates with most everything including WebAPI; it even comes with prebuilt classes to perform the injection.

You will need the Nuget package: Autofac.WebApi2

GlobalConfiguration.Configure(WebApiConfig.Register);
var config = GlobalConfiguration.Configuration;

var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterModule(new ModelsModule());
builder.RegisterModule(new ServiceModule());

var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

This is my Global.asax in the Application_Start. A few things to point out.

  1. The RegisterApiControllers tables the executing assembly (our Api project) and performs conventions based injection (basically it maps anything ending with Controller).
  2. Web API operates off the DependencyResolver pattern. Rather than overloading the Controller factory (what we do in MVC) this enables us to more properly contain our type resolution logic. In this case AutofacWebApiDependencyResolver is provided by the Integration namespace.
  3. My general approach to DI is to use an Autofac Module for each project. These modules specify the injection mappings for types defined in those assemblys. It just keeps things separated in a very nice way.

Once you this in place you can receive injections through the constructor of each controller.  Here is an example of my UserController constructor.

public UserController(IUserService userService, PasswordService passwordService, IAuthorizationService authorizationService)
{
    UserService = userService;
    PasswordService = passwordService;
    AuthorizationService = authorizationService;
}

In the past, I would normally use Property Injection to fulfill my dependency properties. However, recently I have begun to shift to using the constructor as it makes unit testing easier.

This code should just work with your dependency mappings and the code above in the Global.asax.

One of the points of emphasis I have made here is the fact that DI can help with scoping our DbContext to the request level. I do this in my ModelsModule since the context is defined in my Models project and not the web project. Here is the code:

public class ModelsModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        base.Load(builder);

        builder.RegisterType<GiftListContext>()
            .As<IContext>()
            .InstancePerRequest();
    }
}

That is it. The key here is the built in method InstancePerRequest. I also chose to use IContext to define the public pieces of my DbContext but you can omit this and it will still work. I cannot express how nice it is to have this type of flexibility and letting a reliable third party mechanism control this part of the process.

The final bit I want to talk about is authorization. I generally tend to use ActionFilterAttribute types to authorize the user and establish the CurrentUser property so that my calls can reliably run knowing what user is making the request. I wont be going into how to set this up as it varies project to project.

Here is an updated version of the Global.asax to support injecting dependencies into filters.

GlobalConfiguration.Configure(WebApiConfig.Register);
var config = GlobalConfiguration.Configuration;

var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterWebApiFilterProvider(config);
builder.RegisterType<UserAuthenticateFilter>().PropertiesAutowired();
builder.RegisterModule(new ModelsModule());
builder.RegisterModule(new ServiceModule());

var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

One critical note is that Web API (due to the way it is designed) creates Filters as singletons. So, ANY dependency that is not in Singleton scope will cause a scope resolution failure so, the workaround is to utilize a SeviceLocator pattern to resolve the type.  Here is an example:

var authorizationService = (IAuthorizationService)message.GetDependencyScope().GetService(typeof(IAuthorizationService));

This is the the big advantage to the DependencyResolver approach that Web API uses. It allows us to resolve types without have to create something custom.

Hopefully this clears some of this up re: Dependency Injection.

2 thoughts on “Injecting all the WebAPI Things

Leave a comment