Unity - Part 8: Web

Introduction

Long overdue in the Unity series, how to use Unity in a web application. You can find the other posts here (Adding Interfaces), here (Registration by Convention), here (Injecting Values), here (Extensions), here (Aspect-Oriented Programming), here (Dependency Injection) and here (Introduction).

Lifetime Management

So, you want to store instances in the current web request, so that they are only available during the request. The problem is, there is no out of the box functionality in Unity that allows you to do that.

First, you will want to add the Unity.Mvc NuGet package:

image

This gives you a new lifetime manager, PerRequestLifetimeManager, which stores the request in the HttpContext.Current.Items collection. So, in the beginning of the request, you can register an instance using it:

1: unity.RegisterInstance<ILogger>(new FileLogger(“output.log”),

new PerRequestLifetimeManager());

Or you can also register a type, even in Application_Start, because it will only be resolved when explicitly asked for:

   1: unity.RegisterType<ILogger, FileLogger>(new PerRequestLifetimeManager());

The problem with this approach is that entities instantiated by Unity that implement IDisposable will not be disposed of automatically at the end of the request. For that, we need something else: UnityPerRequestHttpModule. Since this is a regular IHttpModule, we can register it on the Web.config file. What it does is, at the end of the request, it iterates through all of the instances that Unity created using the PerRequestLifetimeManager which happen to be IDisposable and will dispose of them. Mind you, even if this comes in a package called Unity.Mvc, you can certainly use it with Web Forms.

Dependency Resolution

MVC uses it’s own dependency resolution facility, DependencyResolver. Unity.Mvc includes an adapter for it, UnityDependencyResolver, that you use as this:

   1: DependencyResolver.SetResolver(new UnityDependencyResolver(unity));

This way, whenever MVC needs to resolve one of its components, it will delegate this to Unity.

Filters

ASP.NET MVC has the concept of filters, which offer a sort of Aspect-Oriented Programming model. Filters can be applied to either action methods or the whole controller, and can be of the following kind:


Normally, these filters are either applied through an attribute or globally. The UnityFilterAttributeFilterProvider class can be used to retrieve filters registered in Unity instead. You use it as:

   1: var oldProvider = FilterProviders.Providers.SingleOrDefault(f => f is FilterAttributeFilterProvider);
   2:  
   3: if (oldProvider != null)
   4: {
   5:     FilterProviders.Providers.Remove(oldProvider);
   6: }
   7:  
   8: FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(unity));

If you have registered components that implement one of the filter interfaces, they will be injected automatically.

Creating Controllers

The class that MVC uses to create controllers is DefaultControllerFactory. It does its job by inspecting the well-known Controllers namespace of the containing web application assembly. We can create a class that inherits from DefaultControllerFactory and first tries to lookup the controller from Unity:

   1: public class UnityControllerFactory : DefaultControllerFactory
   2: {
   3:     private readonly IUnityContainer unity;
   4:  
   5:     public UnityControllerFactory(IUnityContainer unity)
   6:     {
   7:         this.unity = unity;
   8:     }
   9:  
  10:     public override IController CreateController(RequestContext requestContext, string controllerName)
  11:     {
  12:         var controller = unity.Resolve<IController>(controllerName);
  13:  
  14:         if (controller == null)
  15:         {
  16:             controller = base.CreateController(requestContext, controllerName);
  17:         }
  18:  
  19:         if (controller != null)
  20:         {
  21:             unity.BuildUp(controller.GetType(), controller);
  22:         }
  23:  
  24:         return (controller);
  25:     }
  26: }

And for the registration:

   1: ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(unity));

Model Binding

Model binding occurs when you call an action method that takes as one of its parameters a class. MVC automatically creates a class of the proper type, but you can add Unity to the loop, in cases where it is not so easy to achieve. For example, consider an action method that receives an ILogger instance. By applying a custom model binder (IModelBinder), you can have MVC resolve it automatically:

   1: public sealed class UnityModelBinder : IModelBinder
   2: {
   3:     private readonly IUnityContainer unity;
   4:  
   5:     public UnityModelBinder(IUnityContainer unity)
   6:     {
   7:         this.unity = unity;
   8:     }
   9:  
  10:     #region IModelBinder Members
  11:  
  12:     public Object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
  13:     {
  14:         return (this.unity.Resolve(bindingContext.ModelType));
  15:     }
  16:  
  17:     #endregion
  18: }

Its registration:

   1: ModelBinders.Binders.Add(typeof(ILogger), new UnityModelBinder(unity));

You can add as many types as you like, MVC will try each of them until one returns a valid instance.

                             

No Comments

Add a Comment

As it will appear on the website

Not displayed

Your website