MVC Based ASP.NET Application with Dependency Injection






4.30/5 (9 votes)
A sample MVC based ASP.NET application with Dependency Injection
Introduction
This is my first article on MVC framework and Dependency Injection (DI) which will explain in a step-by-step manner how to use Unity Application block with an ASP.NET web application which is built on MVC framework.
What is ASP.NET MVC Framework?
The MVC (Model View Controller) is a design pattern where the application flow is mediated by a central controller. The controller delegates requests/actions to an appropriate handler. The controller is the means by which the user interacts with the web application/views. The controller is also responsible for sending and receiving the data from the model.
Microsoft ASP.NET MVC 1.0 is a framework built on top of Microsoft .NET 3.5 framework which implements the MVC pattern. We can also implement custom MVC framework using core ASP.NET framework using HttpHandler
s which is not in the scope of this article.
What is Unity Application Block?
In recent times, one of the most used architectures is the container based architecture. The main purpose of the container based architecture is to achieve IOC (Inversion of Control). The DI (Dependency Injection) is the method which is used to achieve IOC (Inversion of Control). Unity Application Block (Part of Microsoft Enterprise library 4.1) is Microsoft’s answer for container based architecture. There are different container based frameworks available in the market e.g. Castle Windsor.
What is the Advantage of Using Container Based Architecture in MVC Application?
While implementing MVC framework in ASP.NET application, we need to invoke model class methods from controller class to retrieve the data from database or any other data source. At that time, we need to create the objects of Model
class in Controller
class using new
operator. This will end up in a strong coupling between Controller and Model. By introducing the component architecture, we are moving the responsibility of creating Model
objects from Controller
to Unity Framework.
Background
Understanding of MVC (Model View Controller), DI (Dependency Injection) and IOC (Inversion of Control) Design patterns are advantageous. The code relays on Microsoft Enterprise library 4.1 and Microsoft ASP.NET MVC 1.0 framework. So an understanding of this framework will be helpful.
Using the Code
You can download the MvcDI.zip file, but you must have Microsoft .NET 3.5 SP1, Microsoft ASP.NET MVC 1.0 and Microsoft Enterprise library 4.1 installed on your machine.
How Did I Create the Project?
In this section, I will describe how I created the project. The steps are listed in sequence and are numbered.
Step 1: Create MVC Enabled ASP.NET Web Application
1.1 Start the Visual Studio 2008 Application and select the New Project from the file menu.
1.2 Select the ASP.NET MVC Web Application template and create the project.
1.3 Delete all the folders which are created (by default) under Views folder.
1.4 Delete all the classes which are created (by default) under Controllers and Models folder.
1.5 Add reference to the following DLLs which are part of Microsoft Enterprise library 4.1.
- Microsoft.Practices.ObjectBuilder2
- Microsoft.Practices.Unity
- Microsoft.Practics.Unity.Configuration
Step 2: Create Model Layer
2.1 Add a new class CustomerEntity.cs under the Models folder.
This class acts as a Data Transfer Object(DTO) which is used to transfer the data across the layers:
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
namespace MvcDI.Models
{
/// <summary>
/// This is the Customer Entity class Defines the properties
/// </summary>
public class CustomerEntity
{
private string _strCustomerName;
private string _strCustomerID;
private string _strCity;
//Parameterised constructor for setting the property values
public CustomerEntity(string strCustomerID,
string strCustomerName, string strCity)
{
CustomerID = strCustomerID;
CustomerName = strCustomerName;
CustomerCity = strCity;
}
//Name of the Customer
public string CustomerName
{
set
{
_strCustomerName = value;
}
get
{
return _strCustomerName;
}
}
//Customer ID
public string CustomerID
{
set
{
_strCustomerID = value;
}
get
{
return _strCustomerID;
}
}
//Customer City
public string CustomerCity
{
set
{
_strCity = value;
}
get
{
return _strCity;
}
}
}
}
2.2 Add a new Interface ICustomer.cs under the Models folder.
This Interface defines the methods which need to be implemented by the Customer
class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MvcDI.Models
{
public interface ICustomer
{
IList<CustomerEntity> LoadCustomers();
}
}
2.3 Add a new class Customer.cs which implements ICustomer
under the Models folder.
This is the model class responsible for generating data.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections;
namespace MvcDI.Models
{
/// <summary>
/// This is the Model class responsible for generating data
/// In Actual Scenario you can connect to Database and fetch the data using ADO.NET
/// </summary>
public class Customer:ICustomer
{
//Populates and returns the CustomerEntity List
public IList<CustomerEntity> LoadCustomers()
{
IList<CustomerEntity> customerList = new List<CustomerEntity> {
new CustomerEntity("ID101", "Anil", "Paris"),
new CustomerEntity("ID101", "Sunil", "Bangalore"),
new CustomerEntity("ID101", "Roy", "London"),
};
return customerList;
}
}
}
Step 3: Create Controller Layer
3.1 Add a new class CustomerController.cs under the Controllers folder.
The CustomerController
class supports the constructor based dependency injection which pushes the dependencies into a concrete class through constructor arguments.
The ViewCustomer()
method represents the action
method. The Controller
base class has a "ViewData
" dictionary property that can be used to populate data that you want to pass to a View. In this code snippet using the ViewData
dictionary, customer data retrieved from the model layer is passed on to the view layer.
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using MvcDI.Models;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Practices.Unity;
/// <summary>
/// This is the Customer Controller class
/// </summary>
namespace MvcDI.Controllers
{
public class CustomerController:Controller
{
// Declares the _customer of type ICustomer
ICustomer _customer;
//Invoked by Unity Framework
public CustomerController(ICustomer customer)
{
_customer = customer;
}
//Specifies the action
public ActionResult ViewCustomer(string s)
{
//Invokes the Model Layer.
//The _customer object is created by Unity framework
IList<CustomerEntity> customerList =_customer.LoadCustomers();
//Assigns to ViewData
ViewData["custList"] = customerList;
return View();
}
}
}
Step 4: Create View Layer
4.1 Add a new WebForm
with the name ViewCustomer.aspx and put it in a sub folder called Customer under the Views folder.
ViewCustomer.aspx
The BoundColumn
in the data DataGrid
control specifies the fields' needs to bind from the data source.
<%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="ViewCustomer.aspx.cs" Inherits="MvcDI.Views.ViewCustomer" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>View Customer</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:DataGrid ID="dtgCustomer" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundColumn DataField="CustomerID" HeaderText="Customer ID">
</asp:BoundColumn>
<asp:BoundColumn DataField="CustomerName" HeaderText="Customer Name">
</asp:BoundColumn>
<asp:BoundColumn DataField="CustomerCity" HeaderText="Customer City">
</asp:BoundColumn>
</Columns>
</asp:DataGrid>
</div>
</form>
</body>
</html>
ViewCustomer.aspx.cs
One interesting point we need to note here is that ViewCustomer
class is derived from ViewPage
(which is a subclass of the existing Page
class) class instead of Page
class.The ViewPage
base class provides us with a ViewData
dictionary property that we can use within the view page to access the data objects that were added by the controller.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcDI.Models;
namespace MvcDI.Views
{
public partial class ViewCustomer :ViewPage
{
protected void Page_Load(object sender, EventArgs e)
{
//Receives the CustomerList which is passed from Controller
dtgCustomer.DataSource = (IList<CustomerEntity>)ViewData["custList"];
dtgCustomer.DataBind();
}
}
}
Step 5: Create a UnitFactory Class which Inherits from DefaultControllerFactory
The Unity factory class is responsible for creating controller instances.
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Microsoft.Practices.Unity;
using System.Web.Mvc;
namespace MvcDI
{
public class UnityFactory : DefaultControllerFactory
{
IUnityContainer _container;
public UnityFactory(IUnityContainer container)
{
_container = container;
}
//Returns the Controller Instance
protected override IController GetControllerInstance(Type controllerType)
{
if (controllerType!= null)
return _container.Resolve(controllerType) as IController;
else
throw new ArgumentNullException("Control Type is not available");
}
}
}
Step 6: Add the Following Contents to the Global.asax.cs File
In the RegisterRoutes
method, user can specify the Action and Controller names. The controller name is the name of the controller class by just eliminating the word "Controller
".
The Application_Start
method is responsible for initializing the unity container, sets the controller factory and registers a type with the container. The RegisterRoutes()
method creates the route table.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Practices.Unity;
using MvcDI.Models;
namespace MvcDI
{
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
//Specifies the Controller and the Action.
new { controller = "Customer",
action = "ViewCustomer", id = "" } // Parameter defaults
);
}
protected void Application_Start()
{
//Initializing the Unity container
IUnityContainer container = new UnityContainer();
IControllerFactory factory = new UnityFactory(container);
//setting the Controller factory for the Unity Container
ControllerBuilder.Current.SetControllerFactory(factory);
//Registering the ICustomer Interface and Customer class
//with Unity Container
//This can be configured via Web.config as well
container.RegisterType<ICustomer, Customer>();
RegisterRoutes(RouteTable.Routes);
}
}
}
Step 7: Build and Run the Application
History
- 21st January, 2010: First version