Click here to Skip to main content
15,881,089 members
Articles / Web Development / ASP.NET

Model View Presenter Pattern Implementation in ASP.NET

Rate me:
Please Sign up or sign in to vote.
4.58/5 (6 votes)
8 Dec 2010CPOL3 min read 38.5K   901   15   6
This article shows how to implement model view presenter(MVP) pattern in ASP.NET

Introduction & Background

Model View Presenter (MVP) is a design pattern used for web as well as Windows application. It is especially used where the application has some user interface for interaction like Winform for Windows app and Webform for web app. In this tutorial, I will show you how to implement MVP in web app as well as Windows app. Another important aspect of MVP pattern is to unit test your whole interface as well as business layer. This really comes in very handy when the application size becomes really very big. The main objective of MVP is Separation of Concern or Loosely Couple the entire system, so that we can test each part of the application.

Using the Code

For example purposes, I will take the Northwind database. I generally use LINQ for accessing database so I have created a dbml for the whole bunch of Northwind database.

Here, we can represent data layer as our model. Frankly speaking, model represents the datalayer and datalayer could be your traditional classes to access database or some services to access database. Here, we will use LINQ classes for our datalayer.

The web interface is very simple in order to make the illustration purpose easy. Let’s talk about our web interface. It will load with all categories and for category selection; it will show the list of products under the selected category. It should have one dropdownlist to hold all the categories. When user selects the category from category listbox, a gridview will be shown with all the products under the category. It’s obvious that we have two events; one is pageload on which all the categories will be shown in the category list; another is selected index change of the dropdownlistbox on which the products will be populated for the selected category in the products gridview. Also there should be some list/collection classes to hold the list of category/product.

So for our view, we will create the interface and one delegate. The code is shown below:

C#
public delegate void CategoryChangeEventHandler(object source, CategoryEventArgs e);

    public interface IProductListing
    {
        IEnumerable<category /> Categories { get; set; }
        IEnumerable<product /> Products { get; set; }

        event EventHandler ListingCategory;
        event CategoryChangeEventHandler ChangeCategory;
    }

The code is very simple to understand. We declare two enumerable interfaces to hold the list of category/product and two events; one is listing of category and another is category changing. In ChangeCategory event, we declare a custom eventargs class to hold the selected category id. The code for CategoryEventArgs is shown below:

C#
public class CategoryEventArgs : EventArgs
    {
        private Int16 _CategoryID;

        public CategoryEventArgs(Int16 CategoryID)
        {
            this._CategoryID = CategoryID;
        }

        public Int16 CategoryID
        {
            get
            {
                return this._CategoryID;
            }
            set
            {
                this._CategoryID = value;
            }
        }
    }

Let’s show the code for the presenter class. The Presenter class is responsible to do something when view raises an event and presenter will respond to the event. To get the view instance, we pass the view through the presenter’s constructor. This method is called constructor injection – a Dependency Injection method. Then, we will subscribe the view events with methods declared in the presenter. The code is shown below:

C#
public class ProductListingPresenter
{
    IProductListing _view;
    
    public ProductListingPresenter(IProductListing view)
    {
        this._view = view;
        this._view.ListingCategory += this.OnCategoryListing;
        this._view.ChangeCategory += this.OnCategoryChanged;
    }
    
    private void OnCategoryListing(object source, EventArgs e)
    {
        NorthwindDataContext oDataContext = new NorthwindDataContext();
        this._view.Categories = from category in oDataContext.Categories
                                select category;
    }
    private void OnCategoryChanged(object source, CategoryEventArgs e)
    {
        NorthwindDataContext oDataContext = new NorthwindDataContext();
        this._view.Products = from product in oDataContext.Products
                              where product.CategoryID == e.CategoryID
                              select product;
    }
}

Here, you can see that the view is passed through the presenter using constructor injection. Now we subscribe the ListingCategory event of the view with presenter’s OnCategoryListing method. Also we subscribe the ChangeCategory event of the view with the presenter’s OnCategoryChanged method.

Within these methods, we call the LINQ classes to populate the data and set the data through view’s property. That’s it and we can test our whole application.

At the start, I mentioned that MVP pattern really makes unit testing easier. In context to this example, we don’t need to write the aspx pages to test the application. We will write a mock class to test the application functionalities and later on we put the code in the aspx page.

Here is the code for the mock class:

C#
public class MockProductListing : IProductListing
    {
        IEnumerable<category /> _categories;
        IEnumerable<product /> _products;

        public void TestPageLoad()
        {
            EventHandler handler = this.ListingCategory;
            if (handler != null)
            {
                handler(this, new EventArgs());
            }
        }
        public void TestProductListingByCategory()
        {
            CategoryChangeEventHandler handler = this.ChangeCategory;
            if (handler != null)
            {
                CategoryEventArgs oArgs = new CategoryEventArgs(Convert.ToInt16(1));
                handler(this, oArgs);
            }
        }

        #region IProductListing Members

        public IEnumerable<category /> Categories
        {
            get { return this._categories; }
            set { this._categories = value; }
        }

        public IEnumerable<product /> Products
        {
            get { return this._products; }
            set { this._products = value; }
        }

        public event EventHandler ListingCategory;
        public event CategoryChangeEventHandler ChangeCategory;
        #endregion
    }

In the mock class, we need to implement the view interface. We will test only two events; one is pageload; another is category dropdownlist selected index changed. You can see, I have written two test methods to test these two events.

Finally, we will write the test methods.

C#
[TestMethod]
public void PageLoad()
{
    List<category> categories = new List<category>();
    MockProductListing _view = new MockProductListing();
    ProductListingPresenter _presenter = new ProductListingPresenter(_view);
    _view.TestPageLoad();
    foreach (Category cat in _view.Categories)
    {
        categories.Add(cat);
    }
    Assert.AreEqual(8, categories.Count);
}

[TestMethod]
public void TestProductsByCategory()
{
    List<product> products = new List<product>();
    MockProductListing _view = new MockProductListing();
    ProductListingPresenter _presenter = new ProductListingPresenter(_view);
    _view.TestProductListingByCategory();
    foreach (Product prod in _view.Products)
    {
        products.Add(prod);
    }
    Assert.AreEqual(12, products.Count);
}

Run the test methods and you will find the expected results.

So now, you can realize how MVP helps to test our application code. In the original representation, we just need to copy the mock class’s code to the aspx page.

History

  • 8th December, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
India India
A community lover and consultant working with Microsoft suite of products. Since 2005, he has been working in application development and maintenance using different Microsoft products. During his leisure time, he prefers to serve different Microsoft communities and learning new technologies. You can reach him at his blog DotNet Artisan

Comments and Discussions

 
QuestionNo MVC? Pin
stevenlauwers2213-Dec-10 5:00
stevenlauwers2213-Dec-10 5:00 
AnswerRe: No MVC? Pin
Chris at M13-Dec-10 11:13
Chris at M13-Dec-10 11:13 
AnswerRe: No MVC? Pin
De, Subhendu13-Dec-10 18:29
De, Subhendu13-Dec-10 18:29 
GeneralRe: No MVC? Pin
DelGator21-Dec-10 12:41
DelGator21-Dec-10 12:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.