Dependency Injection in MVC 3 Was Made Easier
In the past I wrote apost that showed how to implement Dependency Injectionusing Unity in ASP.NET MVC framework. This post revisits that post and shows how you can do the same thing easily in MVC 3. Pay attention that the supplied code is based on MVC 3 beta and may change in the future.
The IDependencyResolver and DependencyResolver
MVC 3 introduces a new interface – the IDependencyResolver. This interface enables service location by providing two methods:
- GetService(Type serviceType)– this method gets a service type and returns an object if the resolver succeeded in resolving the type. If the resolver couldn’t resolve the type you must return null in order to activate the default MVC behavior.
- GetServices(Type serviceType)– this method gets a service type and returns an IEnumerable<object> of all the resolved objects. If the resolver couldn’t resolve the type you must return an empty collection to activate the default MVC behavior.
The DependencyResolver is a static class that you can use to register your custom IDependencyResolver. After you implement the IDependencyResolver, you set it in the DependencyResolver using one of the SetResolver overloaded methods. Then you will be able to use the Current property to get the current DependencyResolver in order to resolve types. If you don’t like to use the DependencyResolver ability you need to implement nothing there is default resolving behavior that is built inside the MVC implementation.
Building and Using a UnityDependencyResolver
Here is a simple implementation of a UnityDependencyResolver:
publicclass UnityDependencyResolver : IDependencyResolver
{
#region Members
private IUnityContainer _container;
#endregion
#region Ctor
public UnityDependencyResolver(IUnityContainer container)
{
_container = container;
}
#endregion
#region IDependencyResolver Members
publicobject GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (Exception ex)
{
returnnull;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch (Exception ex)
{
returnnew List<object>();
}
}
#endregion
}
In order to use this resolver the appropriate place to build the container is the Global.asax file. Here is the implementation:
publicclass MvcApplication : System.Web.HttpApplication
{
publicstaticvoid RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
publicstaticvoid RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protectedvoid Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
var container = InitContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
privatestatic IUnityContainer InitContainer()
{
var container = new UnityContainer();
// Register the relevant types for the
// container here through classes or configuration
container.RegisterType<IMessageService, MessageService>();
return container;
}
}
As you can see I added the initialization of the container and also I set the DependencyResolver to the Unity implementation. The Message service and the controller are the same classes that I showed in my previous post:
publicinterface IMessageService
{
string GetMessage();
}
publicclass MessageService : IMessageService
{
#region IMessageService Members
publicstring GetMessage()
{
return"Hello Controller!";
}
#endregion
}
and
publicclass HomeController : Controller
{
#region Members
[Dependency]
public IMessageService MessageService { get; set; }
#endregion
#region Actions
public ActionResult Index()
{
ViewModel.Message = MessageService.GetMessage();
return View();
}
public ActionResult About()
{
return View();
}
#endregion
}
After running this example we will get the following expected result:
Summary
Let sum up, in MVC 3 beta there is a new way to use DI and IoC containers by implementing the IDependencyResolver interface and registering it in the DependencyResolver static class. There are other injection points that you can use like the IControllerActivator which I’ll write about in a following post.