In this exercise you will learn how to apply Dependency Injection into a View by using new MVC 3 Features for Unity Integration. In order to do that, you will call a custom service inside the Store Browse View that shows a message with an image below. The service will introduce a new dependency inside the view as it has to be initialized in a point.
Then, you will integrate the project with Unity Application Block and create a Custom Dependency Resolver to inject the dependencies.
Task 1: Creating a view that consumes a service
In this task you will create a view that performs a service call to generate a new dependence. The mentioned service is a simple messaging service example that is included in this solution.
- Open the begin solution MvcMusicStore.sln at Source\Ex02-Injecting View\Begin
- Include MessageService.cs and IMessageService.cs classes from Source\Assets\MessageService folder inside /Services folder.
Note:the IMessageService interface defines two properties that are implemented by the MessageService class. These properties are Message and ImageUrl and are defined to hold the message and Url of the image to be displayed. - Create the folder /Pages at project root, and then add the class MyBasePage.cs from Source\Assets\BasePage. The base page you will inherit from has the following structure:
(Code Snippet – Ex02 Injecting Views – MyBasePage – CSharp)
C# - MyBasePage.cs
Copy Code
using System; using System.Collections.Generic; using System.Linq; using System.Web; using Microsoft.Practices.Unity; using MvcMusicStore.Services; namespace MvcMusicStore.Pages { public class MyBasePage : System.Web.Mvc.ViewPage<MvcMusicStore.ViewModels.StoreBrowseViewModel> { [Dependency] public IMessageService MessageService { get; set; } } }
Note:On behalf of a technical reason coming from the ASP.NET engine, the dependency at IMessageService interface can’t be included into the respective View Model Class.
The class MyBasePage intercepts the relationship between the View and the View-Model so the dependency injection at MessageService can now be inherited by the View. - Open Browse.aspx view from /Views/Store project folder, and make it inherit from MyBasePage.cs:
C#
Copy Code
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="MvcMusicStore.Pages.MyBasePage" %>
- Include in Browse view a call to MessageService, that will display an image and a message retrieved by the service:
HTML
Copy Code
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="MvcMusicStore.Pages.MyBasePage" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Browse Albums </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <div> <%= this.MessageService.Message %> <br /> <img alt="<%: this.MessageService.Message %>"src="<%: this.MessageService.ImageUrl %>" /> </div> …
Task 2: Including a custom Dependency Resolver and a Custom View Page Activator
In the previous task you injected a new dependency inside a view to perform a service call inside it. Now, you will start solving that dependence by implementing the new MVC 3 Dependency Injection Interfaces IViewPageActivator and IDependencyResolver.
You will include in the solution an implementation of IDependencyResolver that will deal with service retrieval by using Unity. Then you will include another custom implementation of IViewPageActivator interface that will solve the creation of Views.
Note: |
|---|
| Note: MVC 3 implementation for Dependency Injection had simplified the interfaces for service registration. IDependencyResolver and IViewPageActivator are a part of the new MVC3 features for Dependency Injection. - IDependencyResolver interface replaces the previous IMvcServiceLocator. Implementers of IDependencyResolver must return an instance of the service or a service collection. public interface IDependencyResolver { object GetService(Type serviceType); IEnumerable<object> GetServices(Type serviceType); } - IViewPageActivator interface provides more fine-grained control over how view pages are instantiated via dependency injection. The classes that implement IViewPageActivator interface must create the instance of a view having context information. public interface IViewPageActivator { object Create(ControllerContext controllerContext, Type type); } |
- At the project root folder create a folder Factories and then copy the class CustomViewPageActivator.cs from /Sources/Assets. This class implements the IViewPageActivator interface to hold the Unity Container.
C# - CustomViewPageActivator
Copy Code
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Microsoft.Practices.Unity; namespace MvcMusicStore.Factories { public class CustomViewPageActivator : IViewPageActivator { IUnityContainer container; public CustomViewPageActivator(IUnityContainer container) { this.container = container; } public object Create(ControllerContext controllerContext, Type type) { return this.container.Resolve(type); } } } - Add the class UnityDependencyResolver.cs, which is included in the folder /Sources/Assets, in the project folder /Factories.
C# - UnityDependencyResolver.cs
Copy Code
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Microsoft.Practices.Unity; namespace MvcMusicStore.Factories { public class UnityDependencyResolver : IDependencyResolver { IUnityContainer container; IDependencyResolver resolver; public UnityDependencyResolver(IUnityContainer container, IDependencyResolver resolver) { this.container = container; this.resolver = resolver; } public object GetService(Type serviceType) { try { return this.container.Resolve(serviceType); } catch { return this.resolver.GetService(serviceType); } } public IEnumerable<object> GetServices(Type serviceType) { try { return this.container.ResolveAll(serviceType); } catch { return this.resolver.GetServices(serviceType); } } } }
Note:Note: UnityDependencyResolver class is a custom DependencyResolver for Unity. When a service can’t be found inside the Unity container, base resolver is invocated. - Add the class CustomViewPageActivator.cs in the folder /Factories from Sources/Assets
C# - CustomViewPageActivator.cs
Copy Code
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Microsoft.Practices.Unity; namespace MvcMusicStore.Factories { public class CustomViewPageActivator : IViewPageActivator { IUnityContainer container; public CustomViewPageActivator(IUnityContainer container) { this.container = container; } public object Create(ControllerContext controllerContext, Type type) { return this.container.Resolve(type); } } }
Note:CustomViewPageActivator is responsive for managing the creation of a view by using a Unity container.
In the following task both implementations will be registered, to let the model know where to locate the services and where to create the views.
Task 3: Registering for Dependency Injection in Global.asax.cs Application_Start
In this task you will put all the previous things together to make Dependency Injection Work.
Up to now you have the following elements:
- A Browse View that inherits from MyBaseClass and consumes MessageService.
- An intermediate MyBaseClass class that has dependency injection declared for the service interface.
- A MessageService service and its Interface IMessageService.
- A custom dependency resolver for Unity: UnityDependencyResolver, that deals with service retrieval.
- A View Page activator: CustomViewPageActivator, that creates the page.
To inject Browse View, you will now register the custom dependency resolver into the Unity container.
- Open Global.asax.cs at project root
- Register an instance of MessageService into Unity container that will initialize the service:
(Code Snippet –Ex02 Injecting a View – GlobalAsax Registration – Csharp)
C#
Copy Code
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); var container = new UnityContainer(); container.RegisterType<IStoreService, StoreService>(); container.RegisterType<IController, StoreController>("Store"); var factory = new UnityControllerFactory(container); ControllerBuilder.Current.SetControllerFactory(factory); container.RegisterInstance<IMessageService>(new MessageService { Message = "You are welcome to our Web Camps Training Kit!", ImageUrl = "/Content/Images/logo-webcamps.png" }); } - Register CustomViewPageActivator as a view page activator into Unity container:
(Code Snippet –Ex02 Injecting a View – GlobalAsax Registration 2 – Csharp)
C#
Copy Code
protected void Application_Start() { … container.RegisterInstance<IMessageService>(new MessageService { Message = "You are welcome to our Web Camps Training Kit!", ImageUrl = "/Content/Images/logo-webcamps.png" }); container.RegisterType<IViewPageActivator, CustomViewPageActivator>(new InjectionConstructor(container)); } - Replace MVC 3 default dependency resolver with an instance of UnityDependencyResolver:
(Code Snippet –Ex02 Injecting a View – GlobalAsax Registration 3 – Csharp)
C#
Copy Code
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); var container = new UnityContainer(); container.RegisterType<IStoreService, StoreService>(); container.RegisterType<IController, StoreController>("Store"); var factory = new UnityControllerFactory(container); ControllerBuilder.Current.SetControllerFactory(factory); container.RegisterInstance<IMessageService>(new MessageService { Message = "You are welcome to our Web Camps Training Kit!", ImageUrl = "/Content/Images/logo-webcamps.png" }); container.RegisterType<IViewPageActivator, CustomViewPageActivator>(new InjectionConstructor(container)); IDependencyResolver resolver = DependencyResolver.Current; IDependencyResolver newResolver = new UnityDependencyResolver(container, resolver); DependencyResolver.SetResolver(newResolver); }
Note:ASP.NET MVC3 provides a default dependency resolver class. To work with custom dependency resolvers as the one we have created for unity, this resolver has to be replaced.
Task 4: Running the application
In this task you will run the application to verify that the Store Browser consumes the service and shows the image and the message retrieved by it:
- Press F5 to run the application, where Home page will load.
- Browse to /Store and enter to any of the genres that are shown below. In this example, we enter to “Rock”:

Figure 1
MVC Music Store - View Injection