Total votes: 1
Print: Print Article
Please login to rate or to leave a comment.
Published: 18 Mar 2011
In this article, Brian Mains looks at the various features the MVC framework has exposed to allow support for DI containers.
ASP.NET MVC 3 was released recently with a wide array of new features, one of these being Dependency Injection. The MVC team added support in many areas of the framework, which is where we are going to be focusing on in this article. If you haven't read my previous series on Dependency Injection containers, please refer to the previous articles in this ASP.NET MVC series.
If you don't know what Dependency Injection is, I'll briefly recap: it is a design pattern designed to loosely couple an object and its relationships to other objects, and how those relationships are fulfilled. Typically the responsibility for instantiating an object is delegated to a factory, which contains these mappings that the factory uses to "inject" a reference into that object's constructor or one of its properties. This means that the container not only creates the object itself, but also injects references into the constructor at construction time and into its member properties.
There are many types of DI containers, and in this article, we are not going to look at each of these specifically. Rather, we're going to look at the various features the MVC framework has exposed to allow these tie-ins, and examine one type of container: AutoFac. AutoFac is a pretty capable container, provides multiple registration and extensibility points, and is easy to use.
With MVC 3 introduces the use of a new design pattern: the service locator design pattern. This pattern provides a similar capability to Dependency Injection. Though while the Dependency Injection container typically remains hidden and under-the-scenes, the service locator is a publicly available feature exposed through the IDependencyResolver interface in MVC 3. This interface exposes two methods, GetService and GetServices, all returning mappings from a given type. Our custom implementation uses an AutoFac dependency injection container to serve up the actual references. The DI container is concealed by the service locator, even though the two are working in tandem.
Listing 1: An IDependencyResolver instance using AutoFac
The AutoFac container uses the
RegisterOptional method to find the service; this safely returns null if the object isn't found. Once a custom dependency resolver is in place, the resolver must be registered with the framework. As typical with other services, this registration happens in the global.asax file, during the starting of the application.
Listing 2: Registering the Custom Dependency Resolver
The dependency resolver uses the IContainer reference built during the startup of the application. This reference to the container is stored globally for this example; there are better ways to handle this, but for now, it was easiest to illustrate the example using a static.
The framework makes attempts to resolve most references through the IDependencyResolver; the controller factory, controller activator, view page activator, and other vital components are sought for their existence in the service locator, and if not found, the framework defaults to the previous configuration.
With previous versions of the controller factory, the process of finding a controller and instantiating a controller was handled by the IControllerFactory interface only. The MVC 3 framework has broken out the controller creation process from the factory, but the controller examination process remains with the controller factory. The framework, as previously mentioned, looks within the service locator for this reference; if not present, the DefaultControllerFactory takes over (or other controller factory in place if customized).
Listing 3: Custom Controller Activator
If you don't really care to have this functionality separated out, the old implementation style is still available. For instance, the example controller factory below uses AutoFac to find and create the references to the controller, falling back to
Activator.CreateInstance if the controller isn't found.
Listing 4: Custom Controller Factory
View Page Creation
Similar to controller creation, the view has an IViewPageActivator implementation that supports creating a view instance. In ASP.NET MVC 3, with the addition of Razor, both types of MVC applications compile the view into a class file, sharing a common base class called BuildManagerCompiledView. The view engine uses IViewPageActivator as a means to construct the view. This activator component below uses dependency injection to inject any additional references we may need. Listign 5 contains an example of the activator.
Listing 5: Custom View Page Activator
ASP.NET MVC introduced an aspect-oriented approach to development by adding filters, or attributes that can be applied to an action method to control some portion of the framework process. Some filters control which controller method gets applied to an HTTP request, others run before and after the action/result, and some handle exceptions. Depending on what you want to do depends on the type of filter you create. This has been illustrated in a previous article in this series.
The MVC 3 framework has added a lot of functionality to provide to filters. This subject is worthy of a separate article and can't be discussed in length here; however, note that the IFilterProvider interface gives you the capability to customize the filter finding process for an action.
One of the goals of the third release of the MVC framework was to open up the extensibility, and to borrow from the AOP handbook. This is available through a service locator in the form of IDependencyResolver, which can inject static references, references from a Dependency Injection container, or whatever else an application may need.
In this article, we used AutoFac to serve up references to controllers and view pages, injecting any dependencies that were found. The framework also uses the service locator to inject in core common framework components.
Brian Mains is an application developer consultant with Computer Aid Inc. He formerly worked with the Department of Public Welfare.
In both places of business, he developed both windows and web applications, small and large, using the latest .NET technologies. In addition, he had spent many hou...
This author has published 73 articles on DotNetSlackers. View other articles or the complete profile here.
Please login to rate or to leave a comment.