Thursday, April 14, 2016

Lifetime trick when migrating to mvc.net core 1

Recently while migrating projects from MVC.Net 5 to core 1 rc1 (mvc6 / vNext) I ran into an IoC problem. I was using Autofac as my container, and had just migrated some MVC filters. The filters were registered in the container using Autofac, and bound to MVC as global filters using ServiceFilterAttribute; following the post http://www.strathweb.com/2015/06/action-filters-service-filters-type-filters-asp-net-5-mvc-6/>here
Unfortunately at run time Autofac threw an error “No Scope with a Tag Matching ‘AutofacWebRequest’ “ . There is a reference to the problem on the Autofac site here
The error indicates either
  1. Trying to bind a long-life (singleton) object with a short-life (per request) object.
  2. Trying to resolve a per-request object before there is a request scope.
With these clues I finally worked out the problem, I have a combination of ‘binding’ approaches in my project.
Some services are bound using Autofac modules, here I was using InstancePerRequest() lifetimes. Other services were bound using the MVC container interface, in particular using IServiceCollection.AddScoped().
Using the Autofac MVC extensions, I add the MVC container bindings to the Autofac continer via ContainerBuilder.Populate(). This method maps the service registrations into Autofac. The mapping converts IServiceCollection Scoped bindings to InstancePerLifetimeScope().
Bingo
So some services were bound with InstancePerReqest(), while others with InstancePerLifetimeScope(). After consolidating my bindings to all use InstancePerLifetimeScope(), problem solved.

No comments:

A short list of C# coding issues.

Injecting services into entities It been bugging me for a while now that to use services in a entity can be a bit of pain. It usually starts...