ASP.NET MVC 3 & Unity 2.0: Using XML configuration for design-time configuration

Introduction

In one of my blog post “ASP.NET MVC 3: Dependency injection with Unity 2.0” I explained how to use the Unity 2.0 dependency injection (DI) container in an ASP.NET MVC 3 web application. The example shown in this previous post uses run-time configuration to set up the DI container. A drawback of run-time configuration is, that one needs a reference to the concrete implementations the Unity container should use for dependency injection when setting up the container. In the example the Application_Start method in the Global.asax.cs refers to the concrete implementation Messages of the interface IMessages:

container.RegisterType<IMessages, Messages>();

Unity also support design-time configuration that enables you to uncouple your application from the concrete implementations that should be injected. Based on the project from my previous post (VS 2010 project download), I will show how to use a XML configuration file for design-time configuration.

Implementation

To uncouple the ASP.NET MVC 3 project from the concrete implementations we first create two new class library projects:

  1. MVC3-Unity-Sample.Contracts
  2. MVC3-Unity-Sample.Core

The idea is, that the contracts project defines the interfaces (IMessage in the example) and the core project defines the concrete implementations (Message in the example) and the ASP.NET MVC 3 project only needs a reference to the contracts project and no reference to the core project. In other words: The ASP.NET MVC 3 project does no longer “know” the concrete implementations.

After creating the two new projects we move/rename the IMessage interface and the Message class:

  1. We move MVC3_Unity_Sample.Models.IMessages to MVC3_Unity_Sample.Contracts.IMessages in the contracts project.
  2. We move MVC3_Unity_Sample.Models.Message to MVC3_Unity_Sample.Core.Message in the core project.

Now we need to add a reference the contracts project in the ASP.NET MVC 3 project and the core project because both refer the IMessage interface.

In a second step, we now need to remove the programmatically (run-time) initialization of the Unity container in the Global.asax.cs and add the (design-time) configuration to the Web.config:

  1. Change the method Application_Start in Global.asax.cs to:
    protected void Application_Start()
    {
      AreaRegistration.RegisterAllAreas();
     
      RegisterGlobalFilters(GlobalFilters.Filters);
      RegisterRoutes(RouteTable.Routes);
     
      var container = new UnityContainer().LoadConfiguration();
      DependencyResolver.SetResolver(new UnityDependencyResolver(container));
    }
  2. Add Unity XML configuration to Web.config:
    <configSections>
      <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
    </configSections>
    <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
      <alias alias="IMessages" type="MVC3_Unity_Sample.Contracts.IMessages, MVC3-Unity-Sample.Contracts" />
      <alias alias="Message" type="MVC3_Unity_Sample.Core.Messages, MVC3-Unity-Sample.Core" />
      <container>
        <register type="IMessages" mapTo="Message" />
      </container>
    </unity>

In a last step we customize the Visual Studio build process because the core project needs to be build in order to run the ASP.NET MVC 3 project but VS2010 does not know this dependency. We need to:

  1. Add project (build) dependencies: Solution properties > Common Properties > Project Dependencies > Select MVC3-Unity-Sample project and check the MVC3-Unity-Sample.Core project
  2. Change the output path of the core project: MVC3-Unity-Sample.Core project properties > Build tab > Output path: “..\MVC3-Unity-Sample\bin\“.

Summary

Using Unity design-time XML configuration decouples the application from concrete implementations. For example in a mutlitier architecture one could use this approach to gain more flexibility: One could replace different layers of the application without recompiling because the type mapping is defined in XML configuration files .

You can download a sample Visual Studio 2010 project containing all the source code here.