IoC / DI with MVC attributes

One of my MVC attributes has a service dependency that I was hoping to introduce through a constructor. Obviously, the MVC attribute requires a parameterless constructor.

public MyAttribute() { ... } public MyAttribute(IMyService) { ... } 

I thought I could do an injection of the properties, not the installation of the constructor, however, my controllers (and their attributes) are in a separate class library without reference to the IoC container.

Is there a way to use the service within an attribute filter without reference to the IoC container?

Why use Ninject for MVC3?

thanks

+6
source share
2 answers

I tried to achieve the same day ago. Please read the post here . To bind filters there is built-in functionality.

+1
source

As a general solution (without any special support for integrating your DI infrastructure) MVC3 requests an IDependencyResolver for IFilterProvider . In other words, the trick is this:

  • Remove FilterAttributeFilterProvider from the System.Web.Mvc.FilterProviders collection.
  • Register an IDependencyResolver for your specific DI (if you haven’t already).
  • Register a custom IFilterProvider in your container that can insert the properties of any requested attribute.

It looks like this:

 var container = new [your favorite container]; // 1. Remove the FilterAttributeFilterProvider from the collection. var providers = FilterProviders.Providers .OfType<FilterAttributeFilterProvider>().ToList(); providers.ForEach(p => FilterProviders.Providers.Remove(p)); // 2. Register a IDependencyResolver DependencyResolver.SetResolver(new YourDiResolver(container)); // 3. Register a customer IFilterProvider. container.Register<IFilterProvider, YourAttributeFilterProvider>(); 

YourAttributeFilterProvider will look like this:

 private class YourAttributeFilterProvider : FilterAttributeFilterProvider { private readonly [your favorite container] container; public YourAttributeFilterProvider( [your favorite container] container) : base(false) { this.container = container; } public override IEnumerable<Filter> GetFilters( ControllerContext controllerContext, ActionDescriptor actionDescriptor) { var filters = base.GetFilters(controllerContext, actionDescriptor).ToList(); // Inject properties into attribute here. filters.ForEach(f => container.InjectProperties(f.Instance)); return filters; } } 

Many frameworks, such as Ninject and Autofac, have built-in support for this through MVC integration packages. However, it is important to understand how to do this manually.

Attention:

One big warning about dependency injection in MVC filter attributes. MVC caches attributes and reuses instances throughout the application domain. This means that they practically become single, and they tighten their addictions. In other words: these dependencies will also become singleton, which is also known as a problem with inactive dependencies . Therefore, be sure that you enter only one dots in your attributes, because your production system will be confused by concurrency errors if you do not.

Although most DI frameworks support injection into filter attributes, none of the frameworks can help fix this problem. Thus, the best solution is to keep your attributes passive, as described here and here .

+10
source

Source: https://habr.com/ru/post/899040/


All Articles