Register and test per-request services with Autofac

When we develop web application, like ASP.NET applications, we often need to implement a service with some informations related to the user request, such as session/account infos.

In this case, the service will be tied to the web request lifecycle and there will be an instance of the service for each request.

Autofac help us to manage the instances and the life cycles of these services.

Service

We can develop a simple service that we use for our tests:


public class AccountService
{
private ITokenService _tokenService;

public AccountService(ITokenService tokenService)
{
_tokenService = tokenService;
}
}

Module

In order to register the service, we use an Autofac module:


public class PerRequestModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<AccountService>()
.AsSelf()
.InstancePerRequest()
.WithParameter(new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(ITokenService),
(pi, ctx) => ctx.ResolveKeyed<ITokenService>("singletonTokenService")
));
}
}

The service was defined has InstancePerRequest; we also specified explicitly the implementation of the parameter interface.

And register it in the Autofac container:


var builder = new ContainerBuilder();
...
builder.RegisterModule(new PerRequestModule());
...
containerBuilder = builder.Build();

Test methods

Now, the last step is the test methods:


[Test]
public void should_is_not_the_same_instance_for_different_requests()
{
AccountService accountService1, accountService2;

using (HttpRequestMessage request = new HttpRequestMessage())
{
request.SetConfiguration(httpConfiguration);
var dependencyScope = request.GetDependencyScope();
accountService1 = dependencyScope.GetService(typeof(AccountService)) as AccountService;
}

using (HttpRequestMessage request = new HttpRequestMessage())
{
request.SetConfiguration(httpConfiguration);
var dependencyScope = request.GetDependencyScope();
accountService2 = dependencyScope.GetService(typeof(AccountService)) as AccountService;
}

ReferenceEquals(accountService1, accountService2).ShouldBeEquivalentTo(false);
}

[Test]
public void should_be_able_to_resolve_instance_per_request()
{
using (HttpRequestMessage request = new HttpRequestMessage())
{
request.SetConfiguration(httpConfiguration);
var dependencyScope = request.GetDependencyScope();
AccountService service = dependencyScope.GetService(typeof(AccountService)) as AccountService;

service.Should().NotBeNull();
}
}

In order to be able to test a per-request service, we need an instance of the HttpRequestMessage class and set the configuration with the httpConfiguration defined in the Autofac container; then we can use the request scope to get an instance of our services and make the test.

You can find the source code here.

Register and test per-request services with Autofac

Registering of the ASP.NET MVC Controllers with Autofac

One of the capabilities of Autofac is the integration with the ASP.NET applications.

ASP.NET MVC is a framework thinked to supports the dependency injection, and so we can use Autofac to register the modules that compose the application, such as the controllers.

Therefore, let’s start by implementing the controllers of the application, then we ‘ll add the Autofac module that define the controllers registration.

Controllers

We implement two controllers, a Controller and an ApiController:

public class HomeController : Controller
 {
 LoggerService _loggerService;

public HomeController(LoggerService loggerService)
 {
 _loggerService = loggerService;
 }
 }

The second one is the Web Api:

public class AccountController : ApiController
 {
 LoggerService _loggerService;

 public AccountController(LoggerService loggerService)
 {
 _loggerService = loggerService;
 }
 }

Autofac module

The first step is install the two autofac packages needed for the integration with ASP.NET:

install-package Autofac.Integration.Mvc
install-package Autofac.Integration.WebApi

Now we can register the controllers with an Autofac module:

public class PerRequestModule : Module
 {
 protected override void Load(ContainerBuilder builder)
 {
 var controllersAssembly = Assembly.GetAssembly(typeof(HomeController));
 var apiControllersAssembly = Assembly.GetAssembly(typeof(AccountController));

 builder.RegisterControllers(controllersAssembly);
 builder.RegisterApiControllers(apiControllersAssembly);
 }
 }

By using the reflection, we can register all the controllers in one shot.

The module needs to be registered in the autofac container:

var builder = new ContainerBuilder();
....
builder.RegisterModule(new PerRequestModule());
...
containerBuilder = builder.Build();

DependencyResolver.SetResolver(new AutofacDependencyResolver(containerBuilder));

httpConfiguration = new HttpConfiguration
{
DependencyResolver = new AutofacWebApiDependencyResolver(containerBuilder)
};

We built the container and passed that to the AutofacDependencyResolver (Controller) and to the AutofacWebApiDependencyResolver (ApiController).

Tests

Now we can implement the test methods:

public class PerRequestTests : BaseTests
{
[Test]
public void should_be_able_to_resolve_mvc_controller()
{
using (var scope = containerBuilder.BeginLifetimeScope())
{
var controller = scope.Resolve<HomeController>();
controller.Should().NotBeNull();
}
}

[Test]
public void should_be_able_to_resolve_api_controller()
{
using (var scope = containerBuilder.BeginLifetimeScope())
{
var controller = scope.Resolve<AccountController>();
controller.Should().NotBeNull();
}
}
}

As you can see, we initialized a new lifetime scope and tried to resolve the controllers.
You can find the source code here.

Registering of the ASP.NET MVC Controllers with Autofac