ASP.NET MVC and Unity IoC
Since several years, software are becoming increasingly complex. A technique to simplify the maintenance is to use a design pattern that allows to remove the dependencies to difficult parts of the software (loosely-coupled design). The Dependency Injection Pattern is part of these techniques. In this post, I explain how to use the Unity framework in an ASP.NET MVC project.
The main objective of the IoC is to use the Unity framework to register Model Objects, based on the environment where it is used: for production (DataService), for development (DesignDataService) or for unit tests (TestDataService). Whenever a Controller need data from the model, we call a Resolver method (included in my UnityLocator class) that returns the good instance of this model, based on this environment. So, with a simple flag (#DEBUG, IsDesignMode property, …) you can switch from a Design environment to a Production environment. Another interesting point is for Unit Testing, where you can define your sample data in a TestDataService class to validate all of your methods.
To integrate Unity in a ASP.NET project, you can use existing packages like Unity.Mvc, but I prefer define my lightweight class to have all control on it.
-
The first step is to add Microsoft Unity in your existing ASP.NET MVC project.Select the command Project / Manage NuGet Packages and search Unity 4.0 (or more).
-
Add a new project 'Class Library' where all Models and ViewModels (adaptation of your models to your applications, your views).
-
In your Model library, add an interface IDataService that will be implemented by the production service (SqlDataService) and the development service (DesignDataService).
-
In your ASP.NET MVC project: (these classes are downloadable here).
- Add a reference to you Model library (to use IDataService).
- Create a class UnityResolver to manage the Unity framework, with a 'container' for your application.
- Create a class A UnityDependencyResolver used by ASP.NET MVC, in Global.asax.cs and the Mvc.DependencyResolver.Current property embedded by MVC.
- Create a class A UnityLocator to resolve all ViewModels or Models in a single class.
- The UnityLocator is the main custom class to register all ViewModels (or Models) and to be referenced by the Global.ascx.cs.
private UnityContainer _container = new UnityContainer();
public UnityLocator()
{
// Self registration to use it later
_container.RegisterInstance<UnityLocator>(this);
// Registration of DataService
//_container.RegisterType<IDataService, DesignDataService>();
_container.RegisterType<IDataService, SqlDataService>();
// Registration of all ViewModels
_container.RegisterType<HomeViewModel>();
}
public HomeViewModel Home
{
get
{
return _container.Resolve<HomeViewModel>();
}
}
public UnityDependencyResolver UnityDependencyResolver
{
get
{
return new UnityDependencyResolver(_container);
}
}
6. Next, you need to include de DependencyResolver in MVC framework global.ascx.cs file.
protected void Application_Start()
{
// Create and register the IoC Unity resolver
DependencyResolver.SetResolver(new UnityLocator().UnityDependencyResolver);
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
7. Finally, you can use your Data objects in all Controllers. To simplify my code, I’ve created a ControllerBase class with a property Locator.
public abstract class ControllerBase : Controller
{
public UnityLocator Locator
{
get
{
return DependencyResolver.Current.GetService<UnityLocator>();
}
}
}
public class HomeController : ControllerBase
{
public ActionResult Index()
{
var home = this.Locator.Home;
return View(home);
}
}
So, you have a separated library with all Models and ViewModels (without references to your UI or Unity framework). You can create sample data in DesignDataService class, or mokup data in TestDataService for Unit Testings. In a future evolution, you can remove the reference between your ASP.NET MVC project and your Model library, using a configuration file to load dynamically your data models (but I think that is too complex in a first step).
Source code including a sample of this implementation is here : https://github.com/dvoituron/DevAppsPodcast
Resources: https://unity.codeplex.com and http://amzn.com/B00EO89ZM8