The Model-View-Presenter pattern

My job is to develop custom SharePoint solutions (mostly web parts with various business functionality). Since SharePoint doesn’t support ASP.NET MVC I need to work with WebForms. It’s a decent technology, but after working with MVC for years it’s a serious fallback. Fortunately there’s a pattern which helps you maintain clear separation of concerns and loose coupling which lends itself well for ASP.NET WebForms, the Model-View-Presenter pattern.

The main concept behind the pattern is that you have a model you need to work with in your UI, a view which is the UI and a presenter which glues these two together. It’s pretty similar to MVC. I’ve created a sample project and hosted it on GitHub, all the code in this post can be found there.

The Presenter

Let’s check out how the presenter and the view work together. Usually it’s the view that composes the presenter and passes it a reference to itself. Since we’re working with ASP.NET, you could imagine something like this:

Nice and simple. However, I took the concept a little further in the sample project. Here’s my presenter base class:

The view reference isn’t passed in the constructor, instead I resort to method injection. Of course constructor injection would be far better, but due to the inner workings of ASP.NET WebForms, I couldn’t use it. Instead you need to call the Init method with your view instance. Init is a Template Method which calls the virtual, parameterless Init method which you can override in your subclasses.  An example from the code:

PersonPresenter inherits from the previous PresenterBase class and overrides its Init method to supply person data to its view. The main benefit of using a common base class for your presenters is that you don’t have to worry about satisfying the view dependency in every presenter class you create. I don’t think that I need to explain why a generic base class is a good idea.

PersonPresenter has a dependency on an instance of the IPersonFacade interface. What is this interface? It plays the role of the model in this context, but I’ll explain it later.

The View

Let’s see how our view is composed together. In the example our view is deceptively simple, and as a rule of thumb, all views should be simple. They have a single responsibility: provide a user interface for viewing and manipulating your model or, to be more appropriate the part of the model that the presenter serves to it. Our view is composed of an interface and an aspx page, as follows:

As you can see our Default.aspx implements the IPersonView interface. The interface has a single, write-only property which called in the PersonPresenter’s overridden Init method and in the Search method, too. There are two workflows here, one for each page request:

  1. A new request comes in.
  2. Page_Load initializes the presenter with the page class.
  3. The Presenter requests person information from the Model.
  4. The Presenter passes the information to the View.

And one for searching:

  1. The user presses the search button.
  2. The View passes back search criteria to the Presenter.
  3. The Presenter forwards the search criteria to the Model.
  4. The Model returns matching persons to the Presenter.
  5. The Presenter forwards the persons to the View.

In the first use case the view is passive, it just shows the data it gets. In the second case the view plays a more active role, it collects user input and passes it back to the presenter, but after this, it remains passive. The presenter doesn’t directly return information to the view in the search method; instead it uses the indirect property setter. I think the following implementation isn’t correct:

The main problem I see is that directly returning information to the view makes it far more active as it needs to be. Your mileage may vary, but I think keeping views as passive and simple as possible is important.

One last question implementation detail in our view: in the first listing I created an instance of a presenter using the new operator in Page_Load. Now we only have a public property named Presenter with a custom attribute called Inject. In the background there’s the Ninject IoC container resolving dependencies and we’re using property injection here. I didn’t try constructor injection, which would be more appropriate as the presenter of a view is a critical dependency, because ASP.NET WebForms Pages don’t really lend themselves to constructor injection.

To use Ninject with ASP.NET WebForms you could use the Ninject.Web extension. Simply use NuGet:

Install-Package Ninject.Web

This will set up your project so that you can start binding dependencies to implementations.

The Model

Last but not least we need a model. The model could be anything but in our case it’s a façade. Here’s the implementation:

PersonFacade has two dependencies: an instance of the PersonRepository interface, which returns Person information. It’s implemented in the example project as a list which returns hard-coded person classes. PersonFacade’s other dependency is an instance of the IPersonDtoBuilder interface. I got the habit after a dreadful experience from a previous project to never pass entities to the user interface, especially not in ASP.NET WebForms. So I always return Dtos and that’s what PersonDtoBuilder is for. It has a single method, BuildDto which takes a Person instance, and returns a PersonDto. It’s a minimalistic example; in this case the only information omitted in the DTO class is the Id of the person.

So using these two dependencies it grabs Person objects from the repository and returns PersonDto objects with the help of the builder class. That’s all our model does.

You can check out the sample project on GitHub.

 

3 thoughts on “The Model-View-Presenter pattern

  1. Hello Gergely,

    A very good article on how to implement MVP pattern with Ninject. I was looking at the code on Github and I was wondering why did you use WebActivator instead of calling the methods from Application_start? What are the advantages?

    I am using Visual Studio 2008, without the possibility to install packages via NuGet, is there a workaround the WebActivator?

    Thank you very much,
    Mihai

    1. Hello Mihai,

      Sorry for the late reply, I haven’t checked the blog a while.
      This project is mostly an experiment, there’s no real reason why I used WebActivator,
      expect that I wanted to try it. Although WebActivator has some features that you can’t
      really do with global.asax, there is none being used in this project.

      I think it’s safe to simply put the module registration call (in NinjectWeb.cs)
      into the Application_Start method in global.asax. I must emphasize that I haven’t tried it.

      Gergely

      1. Thank you for the comment. I am trying at the moment to convert a webform application into an application based on MVP pattern and was curious why you used WebActivator.

        Very nice blog you run, bookmarked it and will definitely check other interesting articles you have.

        Thank you,

        Mihai

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s