Introduction
Here I am going to give a quick example of using MVP with ASP.NET Web Forms.
Although I have a development history of Web forms and MVC, I have favored MVC in the past few years mainly because it helps separate out the application layers and allows the easier inclusion of unit testing. However my current client has a large collection of ASP.Net Web Forms applications and they have no intention of moving over to MVC. They are interested in unit testing and dependency injection frameworks, so utilising the MVP pattern with web forms was the best path to take.
MVC and MVP
The main difference between MVC and MVP is how views are handled. In MVC it is down to the controller to choose which view is to be sent to the client whereas in MVP there is no real choice the view is managed by a presenter.
Basics of MVP

MVP (Model, View, Presenter)
There are two variants of MVP; Passive View and Supervising Controller. I am going to concentrate on Passive View for this article as that is what I have more experience with and I believe it allows the easier adoption of unit testing although you do end up with a larger solution.
Like more traditional ASP.NET Web Forms applications, you have a main solution with web project within it. But here the web project is a pretty dumb project in regards to business logic. For this example the web project is the View. There can be any number of other projects in the solution, but the main ones are Model (class library), Presenter (class library) and Tests (class library).
It is also acceptable to have a Service project and ViewModel project; but I will not touch on those here.
The key aspect of communication between the View and Presenter is the use of Interfaces.
In this example I am going to create a simple login page which on successful login redirects the user to a secure home page and on failure kicks them back to an error page. Quite simple.
The code behind of an aspx page implements an interface which exists in the Presenter project. This interface exposes properties on the ASPX page like this:
ILoginView.cs
public interface ILoginView
{
string FileName { get; set; }
}
Login.aspx
public partial class Login : BasePage , ILoginView
{
public string FileName { get; set; }
public Login()
{
AuthorizationService = AuthorizationService;
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
var presenter = new LoginPresenter(this, AuthorizationService);
var userName = txtUserName.Text;
var password = txtPassword.Text;
presenter.CheckUser(userName, password);
Response.Redirect(FileName);
}
Line 14: Creates an new instance of the presenter which knows about the ILoginView
and IAuthorizationService
interfaces (don’t worry about the authorization service, it sits in the service project).
Line 19: The CheckUser
method is called which in turn calls the LookupUser
method in the authorization service class. This is where the interaction between Presenter and Model occurs; in practice this service would be separated in to the Service project.
For this to work, we need to be using an IoC (Inversion of Control)/DI (Dependency Injection) framework. I have opted to use Castle.Windsor for this.
public class BasePage : Page
{
public IAuthorizationService AuthorizationService { get; set; }
public BasePage()
{
var installer = new IocConfigurator();
var container = installer.BootstrapContainer();
AuthorizationService = container.Resolve();
}
}
public class IocConfigurator : IWindsorInstaller
{
public IWindsorContainer BootstrapContainer()
{
return new WindsorContainer().Install(FromAssembly.This());
}
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container.Register(Component.For().ImplementedBy());
}
}
I won’t delve into this code too much except to say it basically injects an instance of AuthorizationService
whenever it finds IAuthorizationService
. This is done via the BasePage
class which is inherited by the aspx code behind class.
LoginPresenter.cs
private readonly ILoginView _view;
private readonly IAuthorizationService _authorizationService;
public LoginPresenter(ILoginView view, IAuthorizationService authorizationService)
{
if (view == null)
{
throw new ArgumentNullException();
}
this._view = view;
this._authorizationService = authorizationService;
}
public void CheckUser(string userName, string password)
{
bool isValidUser = _authorizationService.LookupUser(userName, password);
if (isValidUser)
{
_view.FileName = "/Secure/Home.aspx";
}
if (!isValidUser)
{
_view.FileName = "Error.aspx";
}
}
Line 18: If it is a valid user, the properties for the View are set on lines 23 and 29.
Back to Login.aspx line 21: Now the FileName
property has been set, the redirect takes the user there.
As you can see there is not much going on in the View; all the logic is left to the Presenter layer to look-up the user. This separation allows the inclusion of dependency injection (a later post) and unit testing.
Simple Unit Test
[Test]
public void is_user_valid_returns_false()
{
var invalidUserName = "invalid_user";
var invalidPassword = "invalid_password";
var mockAuthService = new Mock();
mockAuthService.Setup(x =>
x.LookupUser(invalidUserName, invalidPassword)).Returns(false);
IAuthorizationService authorizationService = mockAuthService.Object;
var view = new LoginViewStub();
var presenter = new LoginPresenter(view, authorizationService);
presenter.CheckUser(invalidUserName, invalidPassword);
Assert.AreEqual("Error.aspx", view.FileName);
}
Line 13: As you can see here there is a need for a Stub which like the View; implements the same interface.
public class LoginViewStub : ILoginView
{
public string FileName { get; set; }
}
Because we are using an interface for the authorization service; we can easily mock that in the tests and set the return value. Here I am using the MoQ framework.
So there you have it a very simple introduction to using MVP with Web Forms. I have used this methodology on two large projects and it has given me a new respect for Web Forms.
Happy coding.
References
The post Using MVP with ASP.NET Web Forms appeared first on Don't Believe The Type.