09/02/2008

MVC with ASP.NET


Model view controller with ASP.NET

Post was moved to here

 

clip_image001

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

image002

 

 

T

 

image004

 

Our mo

 

MVC with ASP.NET

Model view controller with ASP.NET

 

It’s now generally admitted in the community that Unit testing and TDD (Test Driven Development) are valuable techniques when it comes to increasing the overall quality of our code. Nevertheless unit testing can be costly especially when you’ve applications with a lot of logic implemented in the UI. 

 

Therefore if we want to make our application testable we need to separates the UI from the rest of the application.  Martin Fowler described on his site some patterns that separate and diminish the UI logic to a bare minimum.  They are all variants of the classical MVC (Model View Controller) pattern.  The MVC split the application in 3 parts: the view handles the display, the controller that responds to user gestures and the model that contains the domain logic. 

 

The MVC is the foundation of very popular portal frameworks like Ruby on Rails.  To build web sites applying the MVC pattern with .Net developers can choose among several MVC frameworks like Monorail.  In anyway, MVC frameworks like Monorail are based on completely different paradigm as the ASP.NET framework.  This means that you have to re-learn to program web apps from scratch.  Another setback is that there are no ways to refactor your old ASP.NET applications so that they can fit into the MVC framework.

 

I want to make myself clear, I believe that frameworks like Monorail or the coming System.Web.MVC are the future way of programming web apps in .NET but it demands a considerable amount of effort to learn new frameworks. It’s difficult for someone like me who has invested lots of years in mastering the classical ASP.NET code-behind model to re-learn everything from scratch. In the meantime this should not be an excuse to not make my code more testable.

 

In this post I will explicit through a simple example how to use the model view controller pattern on top of the code-behind model. 

 

We will create a login form with the MVC pattern.

 

Setup your solution

Create a new solution “Zoo” with 3 projects ->

-         ZooWebsite-> ASP.NET web appplication

-         ZooLibrary  -> Class library

-          ZooTest  - Class library

 

- Create a reference from ZooWebsite to ZooLibrary

(ZooWebsite , add reference, project tab select ZooLibrary)

- On ZooLibrary add a reference to System.Web

 

 

The View

To make our code testable it’s very important to be able to decouple the UI from the ASP.NET code-behind.  Therefore we will create an interface our ASP.NET page should implement.  This View interface will represent the contract the UI as to conform to.  When we will test our controller we will not do this with our actual web page but through a mock object that implements the View interface.    

 

Add an interface ILoginView on the project ZooLibrary:

 

namespace ZooApplication.Library

{

     public interface ILoginView

    {

        string ErrorMessage { get;set;}

        string EmailAddress { get;set;}

        string Password { get;set;}

        void RedirectFromLoginPage();

        System.Web.UI.WebControls.Button BtnLogin { get;set;}

    }

}

-> Edit the default aspx page and enter: Welcome you are authenticated!

-> Add the login.aspx to the ZooWebsite project.

 -> Edit the source of the login.aspx part -> add two textboxes, a button, and validators:

 

<%@ Page Language="C#" AutoEventWireup="true" Codebehind="Login.aspx.cs" Inherits="ZooApplication.Website.Login" %>

 

<!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>Login page</title>

</head>

<body>

    <form id="form1" runat="server">

        <div>

                Login form<br />

                <asp:Label ID="LblErrorMsg" runat="server" Text="Invalid login" Visible="false" ></asp:Label><br />

                Email Address:

                <asp:TextBox ID="TxbEmailAddress" runat="server"></asp:TextBox>

                <asp:RequiredFieldValidator ID="RfvEmailAddress" runat="server" ErrorMessage="Enter your email address!"

                    ControlToValidate="TxbEmailAddress">

                </asp:RequiredFieldValidator>

                <asp:RegularExpressionValidator ID="RevEmailAddress" runat="server" ControlToValidate="TxbEmailAddress"

                    ErrorMessage="Invalid email address!" ValidationExpression="w+([-+.']w+)*@w+([-.]w+)*.w+([-.]w+)*">

                </asp:RegularExpressionValidator></div>

            <div>

                Password:

                <asp:TextBox ID="TxbPassword" runat="server"></asp:TextBox>

                <asp:RequiredFieldValidator ID="RfvPassword" runat="server" ErrorMessage="Enter your password!"

                    ControlToValidate="TxbPassword">

                </asp:RequiredFieldValidator>

            </div>

            <div>

                <asp:Button ID="PageBtnLogin" runat="server" Text="Login" />

            </div>

        </div>

    </form>

</body>

</html>

 

 Because the code-behind is not testable and don’t make part of the SUT (Subject Under Test) we want to diminish the code-behind logic to a bare minimum.   The view responsibility is limited to output  the data coming from our model in a human readable way and to expose user input to the controller. 

Therefore we implement our interface through an aspx page that only contains a set of properties that binds data coming from the controller with our web controls. 

Generally we will try to implement all the presentation logic into the controller.  The only exception here will be the RedirectFromLoginPage() method. 

We could use a provider pattern to abstract this from the page but for the sake of simplicity I’ve decided to implement it directly in the page. 

 

 

using System;

using System.Data;

using System.Configuration;

using System.Collections;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using ZooApplication.Library;

 

namespace ZooApplication.Website

{

    public partial class Login : System.Web.UI.

13/02/2007

End To End testing

I truly believe in TDD (Test driven development).  Nevertheless I think that just TDD and refactoring don’t imply that the developers are writing first time right code.  TDD will only test the case the developer has thought of.  It’s a coding practice that is helping in improving the design but it’s not a guarantee for perfect quality.   

On the project we are currently working on, we’ve planned some end to end testing sessions. Each testing session’s goal is to test a couple of stories. We hope that these tests will be helpful to better understand what our end-users really want.   As we don’t have a dedicated QA team the responsibility of the tests is handled by our usability team.  They invited some end users for testing sessions. We already do a lot of tests but this is the first time we are organizing formal end to end tests during the development process. 

Although the first testing session will be held tomorrow I’ve the feeling that the investment we made by preparing these tests is already paying off. Usually a couple of weeks before the delivery date a lot of pressure are put on the head of the team.    The sessions are motivating the team to deliver a complete set of features at regular moments in time.  Because we organised these tests all over the development period we’ve divided the delivery of the product into small releases. The developers are therefore making regular sprints and this is improving our productivity and quality. 

Knowing that the fearless end-users are coming to evaluate our product stimulates us to deliver more quality.  It helped us discover bugs sooner because someone else that is not as close to the code check that the code is doing what he expects.

22:15 Écrit par Geoffrey Vandiest dans Web | Lien permanent | Commentaires (0) | Tags : testing, xp, tdd, usability, end to end |  Facebook |