In the past, I wrote a
post that showed how to implement Dependency Injection using 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
:
public class UnityDependencyResolver : IDependencyResolver
{
#region Members
private IUnityContainer _container;
#endregion
#region Ctor
public UnityDependencyResolver(IUnityContainer container)
{
_container = container;
}
#endregion
#region IDependencyResolver Members
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (Exception ex)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch (Exception ex)
{
return new 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:
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home",
action = "Index", id = UrlParameter.Optional }
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
var container = InitContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private static IUnityContainer InitContainer()
{
var container = new UnityContainer();
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:
public interface IMessageService
{
string GetMessage();
}
public class MessageService : IMessageService
{
#region IMessageService Members
public string GetMessage()
{
return "Hello Controller!";
}
#endregion
}
and:
public class 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's 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.