Introduction
In the past, I wrote a post about How To Use Unity Container In ASP.NET.
In this article, I'm going to show and explain how you can use Unity IoC container in ASP.NET MVC Framework in order to make aspects in our application more decoupled.
Building The Container
As in the previous post, the first thing to do is to build the container itself. I'll use the same method that I used in the previous post in order to persist the Unity container’s state during the application execution. The right place to put the Unity container is as part of the Global.asax file as a property of the current running HTTP application. I'm going to use the same interface that I used in the past which looks like:
public interface IContainerAccessor
{
IUnityContainer Container { get; }
}
After the building of the interface, implement it in the Global
class in the Global.asax file:
public class MvcApplication : HttpApplication, IContainerAccessor
{
#region Members
private static IUnityContainer _container;
#endregion
#region Properties
public static IUnityContainer Container
{
get
{
return _container;
}
}
#endregion
#region IContainerAccessor Members
IUnityContainer IContainerAccessor.Container
{
get { return Container; }
}
#endregion
#region Application Events
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
InitContainer();
ControllerBuilder.Current.SetControllerFactory(typeof(UnityControllerFactory));
}
protected void Application_End(object sender, EventArgs e)
{
CleanUp();
}
#endregion
#region Methods
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" } );
}
private static void InitContainer()
{
if (_container == null)
{
_container = new UnityContainer();
}
_container.RegisterType<IMessageService, MessageService>();
}
private static void CleanUp()
{
if (Container != null)
{
Container.Dispose();
}
}
#endregion
}
The implementation is straightforward. You create a getter for the container which is a member of the HTTP application. Also in the application start event, I register all the relevant dependencies in the container and I dispose the container when the application ends.
The Unity Controller Factory
The real and important change with this new implementation of Global.asax is the setting of the controller factory which you will need to supply. The controller factory's responsibility is to instantiate the relevant controller for the incoming HTTP request. You should implement the IControllerFactory
interface in order to be able to plug in your factory implementation.
The code for the UnityControllerFactory
is as follows:
public class UnityControllerFactory : IControllerFactory
{
#region IControllerFactory Members
public IController CreateController
(RequestContext requestContext, string controllerName)
{
IContainerAccessor containerAccessor =
requestContext.HttpContext.ApplicationInstance as IContainerAccessor;
Assembly currentAssembly = Assembly.GetExecutingAssembly();
var controllerTypes = from t in currentAssembly.GetTypes()
where t.Name.Contains(controllerName + "Controller")
select t;
if (controllerTypes.Count() > 0)
{
return containerAccessor.Container.Resolve
(controllerTypes.First()) as IController;
}
return null;
}
public void ReleaseController(IController controller)
{
controller = null;
}
#endregion
}
The main thing to do is to implement the CreateController
method of the IControllerFactory
interface. I use the request context parameter to retrieve the current application instance and from it, I get the Unity container using the interface of IContainerAccessor
. I also need to instantiate the relevant controller class which is being done by the Unity container for me.
The container will inject the dependencies in the controller by the Resolve
method and we will get the dependency injection functionality that we wanted.
The Class to be Injected
I also wrote a MessageService
which is a simple class that returns a message and inherit
from the IMessageService
which declares the GetMessage
method:
public interface IMessageService
{
string GetMessage();
}
public class MessageService : IMessageService
{
#region IMessageService Members
public string GetMessage()
{
return "Hello Controller!";
}
#endregion
}
The Controller
The last piece in this puzzle is the controller class. I implemented the HomeCotroller
class with the following code:
[HandleError]
public class HomeController : Controller
{
#region Members
[Dependency]
public IMessageService MessageService { get; set; }
#endregion
#region Actions
public ActionResult Index()
{
ViewData["Message"] = MessageService.GetMessage();
return View();
}
public ActionResult About()
{
return View();
}
#endregion
}
The UnityControllerFactory
will inject the dependency of the MessageService
property with the relevant class and it's as simple as that. In order to run this, you'll have to create a new MVC framework application, add the classes I wrote and change the supplied HomeController
to the implementation I wrote.
Summary
Let's sum up. I showed an example of how to use Unity container in ASP.NET MVC Framework application. This is a very simple example that will help you to get started with Unity in your MVC web applications.
History
- 5th August, 2010: Initial post