Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Test Driven Development with ASP.Net and the Model View Presenter Pattern

DISCLAIMER:  This was written all the way back in Feb. 2006 when we thought that MVP with ASP.NET was the only real alternative for somewhat testable web user interfaces.  I thank you for the interest, but there have been better articles written since, and I’d strongly recommend looking at MonoRail or Ruby on Rails or the new MVC framework for ASP.NET if you’re interested in maintainable, testable web applications. Let me make this even clearer, I think the technique in this article is one giant, smelly hack.  The only adequate solution is to dump WebForms, or convince yourself that TDD, Testability, and Separation of Concerns is meaningless 

A friend of mine was asking me a while back about ways to apply the Model View Presenter (the “Humble Dialog Box”) pattern to ASP.Net development to promote easier unit testing of the user interface layer.  Two weeks and a major case of writer’s block later, I finally finished the post.  I wrote a blog post last spring describing the usage of MVP (“The Humble Dialog Box”) with WinForms clients, but web development in general and ASP.Net in specific comes with a different set of challenges. 

 So what are the problems with ASP.Net that MVP Solves? 

If you asked me to name the single most important principle in all of software design, regardless of language, platform, or programming paradigm, I’d say “Separation of Concerns” in a heartbeat.  For the sake of maintainability, each piece of code should have one and only one distinct responsibility.  Even in the initial act of coding I only want to work on one problem at a time.  I want to look at the business logic code without seeing database infrastructure code or HTML construction intermingled with everything else (a huge pet peeve of mine). 

 

The traditional approach for building maintainable user interface code is to separate the typical concerns of a user interface with the Model View Controller (MVC) pattern.  Unfortunately, ASP.Net is optimized for Rapid Application Development, not for creating maintainable code.  A common criticism of the ASP.Net development model (and ASP classic before that) is that it does not enforce or even encourage a clean Model View Controller separation.  Many ASP.Net applications seem to be a jumble of data access code, HTML markup, and business logic, but it doesn’t have to be that way.  By itself, the “code-behind” model in ASP.Net does not do enough to create a good separation of concerns.  Plus it’s difficult to get code-behind code into unit tests. 

 

My preference is to use the Model View Presenter pattern to structure ASP.Net code to create maintainable and testable solutions.  I think of MVP as just a flavor of MVC, but it’s worth stating the differences.  The central fact of MVP architectures is that the “view” is a very shallow wrapper around the actual screen.  Unlike most traditional MVC implementations, the view classes are entirely passive.  The Presenter classes are the active classes that are responsible for initiating the view processing. 

 

The big challenge in unit testing ASP.Net code is the tight coupling to the ASP.Net runtime.  The web controls are very tightly bound to the underlying HttpContext and the web event pipeline, making the user interface code difficult to work with inside an xUnit test harness.  I’ve seen people successfully create fake HttpContext objects in memory, but it really amounts to a hack to test existing legacy ASP.Net code.  You can also use tools like NUnitASP or Selenium to test web applications, but those tests are integration tests, not unit tests.  The best thing to do in my experience is to isolate as much of the functionality as possible away from the ASP.Net runtime into classes that can be easily tested inside of NUnit, and that’s exactly what the MVP pattern does.  Putting this another way, I would suggest that any piece of code that isn’t directly manipulating web controls or parts of the web page should be moved out of the code behind classes and into another class.

 

A lot of .Net literature describes the “Code-Behind” class as the MVC controller.  I think this is dead wrong.  The code-behind is View code, period.  For best results, the presenter should never have any reference to any type in the System.Web namespace. 

 Class Structure of MVP 

The basic concept is simple.  Like the classic Model View Controller pattern, you divide the responsibilities of the web page into separate classes.  In specific, we want to isolate as much of the functionality as possible away from the ASP.Net runtimes.  The functionality of a screen is divided into three parts:

 

  • View classes:  Displays data and relays user input and events to the Presenter. 
  • Presenter classes:  Coordinates communication between the view and the backend service or business layer and is responsible for user interface logic
  • Model classes:  The data being displayed or worked on in the screen.  This is could be either a business domain object(s), a data transfer object, or a lowly DataSet.  The Model is also the state of the user session. 

 A Simple Example 

Let’s dive into some code.  You’re creating a new web screen in a custom workflow application for people to enter and assign “WorkItem’s” to other people.  The screen will have dropdown lists for both the WorkItem category and the assigned user.  In no particular order, let’s start with the Model class.

       public class WorkItem      {            private string _category;            private string _assignedTo;             public string Category            {                  get { return _category; }                  set { _category = value; }            }             public string AssignedTo            {                  get { return _assignedTo; }                  set { _assignedTo = value; }            }             /* Other stuff */      } 

The next step is to create an abstracted interface to represent the View class.  Note that we’re not yet working with any System.Web classes, web pages, or web controls.  The IWorkItemView interface encapsulates all interaction with the ASP.Net runtime.

       // Abstracted interface of the WorkItem View screen      public interface IWorkItemView      {            // Packs the user input into a new WorkItem class            WorkItem WorkItem{get;}             // Sets the values in the dropdown list for the WorkItem assigned to user            string[] AssignmentList {set;}             // Sets the values in the dropdown list for the WorkItem categories            string[] CategoryList {set;}      } 

The backend business and workflow system is accessed by a Façade class with an interface called IWorkItemService.  The backend might be a call to a web service, a remoted object, or an in-process call.  All we’re concerned with in the user interface code is how the presenter interacts with the interface of the service. 

       public interface IWorkItemService      {            void ProcessWorkItem(WorkItem entry);            string[] GetAssignmentListForCategory(string category);            string[] GetCategoriesForRoles(string[] roles);      }  

The lynchpin of the MVP pattern is the Presenter class, WorkItemPresenter.  In this particular user story there is a requirement that the categories displayed in the dropdown on the screen are limited by the role membership of the logged in user.  There is another requirement that the values in the dropdown for the assigned to user are dependent upon the selected category.  The logic that determines the topic and category list is completely isolated from the web page machinery for easier unit testing and maintainability.

             public class WorkItemPresenter      {            private readonly IWorkItemView _view;            private readonly IWorkItemService _service;             // Use “Dependency Injection” to attach the dependencies for the view            // and service.            public WorkItemPresenter(IWorkItemView view, IWorkItemService service)            {                  _view = view;                  _service = service;            }             public void Initialize()            {                  string[] categoryList = this.determineCategoryListFromUserRoles();                  _view.CategoryList = categoryList;            }             public void Submit()            {                  WorkItem item = _view.WorkItem;                  _service.ProcessWorkItem(item);            }             public void ChangeCategory(string categoryName)            {                  string[] assignmentList = _service.GetAssignmentListForCategory(categoryName);                  _view.AssignmentList = assignmentList;            }             public string[] determineCategoryListFromUserRoles()            {                  // Examine the roles on the IPrincipal object and query IWorkItemService for                    // the possible categories                   return new string[0];            }

      }

 

The key things to note here are that the WorkItemPresenter class only depends on the abstracted interfaces for IWorkItemView and IWorkItemService.  The WorkItemPresenter class can now be unit tested with mock objects inside of the NUnit.  WorkItemPresenter is just a “Plain Old CLR Object” that can run and be tested completely outside of the ASP.Net process.  This is strictly personal preference, but I like to build and unit test the Presenter class(es) before I even start to create the ASPX or ASCX’s. 

        [TestFixture]      public class WorkItemPresenterTester      {            private DynamicMock _serviceMock;            private DynamicMock _viewMock;            private WorkItemPresenter _presenter;              [SetUp]            public void SetUp()            {                  _serviceMock = new DynamicMock(typeof(IWorkItemService));                  _viewMock = new DynamicMock(typeof(IWorkItemView));                   _presenter = new WorkItemPresenter((IWorkItemView)_viewMock.MockInstance, (IWorkItemService)_serviceMock.MockInstance);            }

      }

 

Lastly, we’ve got to actually create the web page itself.  I’m using a UserControl as an example, but it could easily be a web page instead.  The WorkItemView UserControl implements the IWorkItemView interface.  It has a reference to an instance of the WorkItemPresenter class with which it communicates.

       public class WorkEntryView : UserControl, IWorkItemView      {            private WorkItemPresenter _presenter;            protected DropDownList assignmentDropdown;            protected DropDownList categoryDropdown;             // The UserControl has a reference to the presenter class            public void AttachPresenter(WorkItemPresenter presenter)            {                  _presenter = presenter;            }             private void Page_Load(object sender, EventArgs e)            {                  categoryDropdown.SelectedIndexChanged += new EventHandler(categoryDropdown_SelectedIndexChanged);            }             #region Web Form Designer generated code             public WorkItem WorkItem {…}              /// <summary>            /// Fill the dropdown list for the possible assignments            /// </summary>            public string[] AssignmentList            {                  set                  {                        assignmentDropdown.Items.Clear();                        foreach (string assignment in value)                        {                              assignmentDropdown.Items.Add(assignment);                        }                  }            }             public string[] CategoryList{…}              // The UserControl immediately relays the user selecting a new Category to the             // presenter object.  The presenter will decide what to do next            private void categoryDropdown_SelectedIndexChanged(object sender, EventArgs e)            {                  string category = categoryDropdown.SelectedValue;                  _presenter.ChangeCategory(category);            }

      }

 

In this case I have an ASPX page that contains a WorkItemView control.  In the Page_Load event of the ASPX page I create a new instance of the WorkItemPresenter, attach it to the user control, and call Initialize() on the presenter class to start the display.

       public class WorkItemPage : System.Web.UI.Page      {            protected WorkEntryView workEntryControl;             private void Page_Load(object sender, System.EventArgs e)            {                  WorkItemPresenter presenter = new WorkItemPresenter(workEntryControl);                  workEntryControl.AttachPresenter(presenter);                   presenter.Initialize();            }

      }

 State Management 

A big challenge in any complex web application is session state.  Think of a typical online store like Amazon.  On one hand the logic involved in maintaining the session state is important and certainly deserving of isolated unit tests.  If I was coding for Amazon, I would certainly want to be writing unit tests around maintaining the state of the “shopping cart” when users select and remove items.  The state of the shopping cart will affect the way the page is displayed and the navigation logic after the page.  That’s exactly the kind of logic that is hard to test if you don’t loosely couple the logic from the HttpContext. 

 

On the other hand, a lot of web screens are only reachable from a series of user actions on previous pages.  The checkout screen can only be reached after working through previous screens.  My first TDD project was an ASP.Net project that had some web pages like this.  We were using NUnitASP to write automated tests.  I didn’t know much about mock objects or MVP (or MVC), so the only way to test my pages and all of their logic was to write tests that progressed through multiple screens just to get to the point where I really wanted to test.  Those tests were laborious to write and very brittle.  Smaller tests are always easier to write and read.  What I’ve learned since then is to either create an abstraction around the state management that the presenter classes depend on, or have another class push the state into the presenter.  I touched on this strategy in an earlier post on mock objects.

 

At some point you do have to test the actual web screens, and it’s a great thing to have automated testing on the user interfaces.  It’s just a theory, but I’d think seriously about creating intermediate integration tests that use stubs for all the backend and state management to isolate the web views.  You can use a dynamic service locator like StructureMap to substitute stubs for the services with configuration, or create separate ASPX pages to host the UserControl’s and presenter classes, but use the stub objects instead.  You could then write much simpler Selenium tests to verify granular parts of the user interface in isolation.  You’ve got to maintain loose coupling between the user interface code and the backend to pull it off though.  As usual, testability and good design practices are very closely aligned.

 User Input Validation 

I’ve had a couple of conversations over the last year on the proper place for the user input validation.  I still think you have to take advantage of the built in validation controls in the ASP.Net views if you can do it in a declarative way.  Any kind of validation more complicated than “this field is required” or numeric validation should probably be put into some sort of presenter class or the model classes.   By and large, you want any kind of code that spawns bugs under automated unit testing.  Input validation definitely meets that criterion. 

 

Something I like to do is use what I think of as “Embedded Controllers.”  You need to be cautious in using the MVP pattern to keep the presenter classes from getting too big with too many responsibilities and preventing the bidirectional view-presenter communication from being way too chatty.  I try to alleviate the presenter “blob” anti-pattern by moving validation logic into other controller classes that are used from within the views.  I also like to move functionality like filtering, paging, and sorting to these secondary controller classes.  It’s just a way of keeping the size of the classes down and maintaining class cohesion. 

 Easier NFit/FitNesse Testing 

We’ve had some success with writing our FitNesse tests directly against the Presenter classes.  We have been making the Fixture class for the screen implement the interface for the view and passing itself into an instance of the Presenter, then letting an ActionFixture drive the screen.  It’s a lot simpler than trying to drive the tests against the screens themselves.  Our sister office is using FitNesse to drive Selenium tests to great effect, but they’re doing it because they don’t have a suitable service layer to test business logic through.  These Fixtures look something like this:

 using System;using fit; namespace WebSample{      public class DataEntryFixture : Fixture, IWorkItemView      {            private string[] _assignments;            private string[] _categories;            private WorkItemPresenter _presenter;             public DataEntryFixture()            {                  _presenter = new WorkItemPresenter(this, new WorkItemService());            }             public WorkItem WorkItem            {                  get { throw new NotImplementedException(); }            }              public string[] AssignmentList            {                  set { _assignments = value; }            }             public string[] CategoryList            {                  set { _categories = value; }            }             public string SelectedCategory            {                  set                  {                        _presenter.ChangeCategory(value);                  }            }      }

}

   Related Concepts 

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in Design Patterns, Test Driven Development. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://pastie.org/724114 Muhammad.Jaelani

    I think MVP it’s good for “Separation of Concerns”
    But , When I want to use State Management in ASP.net.
    Is MVP can do it ??

  • Roman

    The code formatting is very broken (probably due to some site migration or other). While the comment above shows the code with newlines, here’s a better formatted version: http://pastie.org/724114

  • http://www.solicitorslawyers.com.au/Piora/Lawyers_Piora.html Lawyers Piora

    Very difficult to understand. Actually I am a newbie. Thanks for sharing.

  • rookie

    public class WorkItem
    {
    private string _category;
    private string _assignedTo;
    public string Category
    {
    get { return _category; }
    set { _category = value; }
    }
    public string AssignedTo
    {
    get { return _assignedTo; }
    set { _assignedTo = value; }
    } /* Other stuff */
    }

    // Abstracted interface of the WorkItem View screen
    public interface IWorkItemView
    {
    // Packs the user input into a new WorkItem class
    WorkItem WorkItem { get;}
    // Sets the values in the dropdown list for the WorkItem assigned to user
    string[] AssignmentList { set;}
    // Sets the values in the dropdown list for the WorkItem categories
    string[] CategoryList { set;}
    }

    public interface IWorkItemService
    {
    void ProcessWorkItem(WorkItem entry);
    string[] GetAssignmentListForCategory(string category);
    string[] GetCategoriesForRoles(string[] roles);
    }

    public class WorkItemPresenter
    {
    private readonly IWorkItemView _view;
    private readonly IWorkItemService _service;
    // Use “Dependency Injection” to attach the dependencies for the view
    // and service.
    public WorkItemPresenter(IWorkItemView view, IWorkItemService service)
    {
    _view = view;
    _service = service;
    }
    public void Initialize()
    {
    string[] categoryList = this.determineCategoryListFromUserRoles();
    _view.CategoryList = categoryList;
    }
    public void Submit()
    {
    WorkItem item = _view.WorkItem;
    _service.ProcessWorkItem(item);
    }
    public void ChangeCategory(string categoryName)
    {
    string[] assignmentList = _service.GetAssignmentListForCategory(categoryName);
    _view.AssignmentList = assignmentList;
    }
    public string[] determineCategoryListFromUserRoles()
    {
    // Examine the roles on the IPrincipal object and query IWorkItemService for
    // the possible categories return new string[0];
    }

    }

    [TestFixture]
    public class WorkItemPresenterTester
    {
    private DynamicMock _serviceMock;
    private DynamicMock _viewMock;
    private WorkItemPresenter _presenter;
    [SetUp]
    public void SetUp()
    {
    _serviceMock = new DynamicMock(typeof(IWorkItemService));
    _viewMock = new DynamicMock(typeof(IWorkItemView));
    _presenter = new WorkItemPresenter((IWorkItemView)_viewMock.MockInstance, (IWorkItemService)_serviceMock.MockInstance);
    }

    }
    public class WorkEntryView : UserControl, IWorkItemView
    {
    private WorkItemPresenter _presenter;
    protected DropDownList assignmentDropdown;
    protected DropDownList categoryDropdown;

    // The UserControl has a reference to the presenter class
    public void AttachPresenter(WorkItemPresenter presenter)
    {
    _presenter = presenter;
    }
    private void Page_Load(object sender, EventArgs e)
    {
    categoryDropdown.SelectedIndexChanged += new EventHandler(categoryDropdown_SelectedIndexChanged);
    }
    #region Web Form Designer generated code
    public WorkItem WorkItem;
    ///

    /// Fill the dropdown list for the possible assignments
    ///

    ///
    public string[] AssignmentList
    {
    set
    {
    assignmentDropdown.Items.Clear();
    foreach (string assignment in value)
    {
    assignmentDropdown.Items.Add(assignment);
    }
    }
    }
    public string[] CategoryList;
    // The UserControl immediately relays the user selecting a new Category to the
    // presenter object. The presenter will decide what to do next
    private void categoryDropdown_SelectedIndexChanged(object sender, EventArgs e)
    {
    string category = categoryDropdown.SelectedValue;
    _presenter.ChangeCategory(category);
    }

    }

    public class WorkItemPage : System.Web.UI.Page
    {
    protected WorkEntryView workEntryControl;
    private void Page_Load(object sender, System.EventArgs e)
    {
    WorkItemPresenter presenter = new WorkItemPresenter(workEntryControl);
    workEntryControl.AttachPresenter(presenter);
    presenter.Initialize();
    }

    }

    using System;
    using fit;
    namespace WebSample{
    public class DataEntryFixture : Fixture, IWorkItemView
    {
    private string[] _assignments;
    private string[] _categories;
    private WorkItemPresenter _presenter;
    public DataEntryFixture()
    {
    _presenter = new WorkItemPresenter(this, new WorkItemService());
    }
    public WorkItem WorkItem
    {
    get { throw new NotImplementedException(); }
    }
    public string[] AssignmentList
    {
    set { _assignments = value; }
    }
    public string[] CategoryList
    {
    set { _categories = value; }
    }
    public string SelectedCategory
    {
    set
    { _presenter.ChangeCategory(value); }
    }
    }
    }

  • Kaba

    Hey, the newlines in the code examples aren’t showing. Makes it very hard to read. :)

    (tested in fx3 & ie7)

  • http://sm-art.biz ulu

    This, and several other articles, are great examples of what can be done within the Webforms framework. The question is, do we really need to throw it away and switch to MS MVC or MonoRail? The “complex event model” and “you can’t control the html output” arguments are not really convincing. The testability issue is still there: you can’t test a View in MonoRail, right? (You *can* test WebForms views with Ivonna though).

    Sometimes I have user controls so simple that they can be implemented declaratively. Refactoring such a simple thing into MVP would be hell. However, I can always do that in case the control gets more complex. Having no predefined MV* pattern makes it more flexible, even, I dare say, agile.

  • http://www.cerquit.com/blogs Rod

    Hi Jeremy,

    This is a great post. You really rock!

    Btw, I created an MVP article (just yesterday) with sample solution on my site. I think this is very helpfull to MVP fantaics out there besides the advantages you mentioned above it also demonstrate how MVP can be reused in differen presenter (web, web form, mobile, etc)… It also has a sample project to demonstrate mock testing.

    URL: http://www.cerquit.com/blogs/post/MVP-Part-I-e28093-Building-it-from-Scratch.aspx

    In our country MVC is more popular than MVP. I think I’m the only MVP evangelist here.. hehehe… In my previous company I conduct and train engineers on how to use MVP and gradualy they really feel the power…

    This is my first blog after 4 years. Its payback time.

    Cheers,
    Rod

  • Pratik Panchal

    Hi,

    I want to test WCSF ( Web Client Software Factory ) using NUnit Mock objects.

    Can you please help me out?

    Pratik

  • http://www.portraitkingdom.com oil portraits

    I really wonder why way back in college we were never introduced to the advanced knowledge of ASP.net. I noticed that most job hirings lately require knowledge on ASP and it just feels so bad that I can do everything except for the one that requires ASP.

  • Mohammad Azam

    Hi,

    Nice article! One thing is bugging me that in the Page_Load of the page you create a presenter and displays the appropriate view on the page. What will happen when you want to display 10-20 views on the same page? Will you use the same approach of creating the views using presenter. These can be small views like

    1) List Customers
    2) Show Current Time
    3) Show LogName
    5) Show Menu

    Let me know what you think!

  • http://www.gigfodder.com mike

    CAT Tech you have convinced me!

  • http://www.cattechnologies.com Imran Ahmedc

    Dear Manager,

    Hope you are doing great!

    The purpose of this letter is to introduce you to CAT Technology Inc and our Offshore Development services. We are the leading Offshore Development service company in INDIA. We align ourselves with our customers as partners to assist them in achieving their goals and objectives. We would be delighted to demonstrate our offshore Development services to you. Please let me know if you have any software Development work to Outsource?

    Out Team size in INDIA:
    .Net/C# Developers: 90 Members
    Delphi Programmers: 18 Members
    Web developers: 50 Members
    JSP/ Java Programmers: 45 Members
    PHP Programmers: 30 Members
    System/Network Administrators (MCSE) (CCNA) (CCNP):30 Members

    Visit us at— http://www.cattechnologies.com

    View our development office in INDIA :
    You can view our development office in INDIA through this camera.
    Camera Server URL: http://203.197.241.56
    Login: cat
    Password: techno

    Dedicated Staff:
    When you set up an offshore development center with CAT, you get the following:
    All hardware, software licensing and office infrastructure already in place A dedicated team of professionals who will learn your business and become a part of your team. Seamless collaboration between offshore office and client project staff through live chat / email / voice / video .U.S. based contact point to manage all issues throughout the relationship and insure success of all projects. All staff assigned to your team will report directly to you or your project manager and follow your directives and timelines.

    Maintenance Projects:
    Just because your project is complete does not mean you don’t need professional technical support for your existing applications. Our staff are available to you on a dedicated basis to review your existing applications and provide you the support and technical updates that are needed to maintain the competitiveness of your applications. If you are a new customer to CAT, ask us about our maintenance plans that enable you to take care of your application beyond the major development phase. Maintenance Services are available to your regardless where you had your application developed

    Project Based:
    Are you looking for professionals to help you build your projects? If so, consider CAT as your world class partner. We will work closely with you to understand your project’s requirements, deadlines, technologies and needs to determine the best team to make your project a success. Also, you can decide whether you plan to manage the project internally and utilize our development and testing resources, or prefer to have one of our project managers lead the team.

    Wide range of PHP Services we provide:
    1. PHP Programming
    2. Database development (php/mysql,)
    3. MYSQL PHP Programming, script installing, modification, and PHP Script repairs.
    4. Custom web site design/redesign and development
    5. Custom PHP and MYSQL web programming
    6. PHP shopping cart
    7. PHP forum
    8. PHP content management system

    Wide range of .Net Services we provide:
    1. Application Development using .NET
    2. Designing and Programming using .NET
    3. Migration web based and other applications to .NET
    4. Porting of Legacy applications to .NET based applications
    5. Support and Enhancement of existing applications in .NET
    6. User needs assessment / functional spec writing
    7. Website architecture design
    8. User Interface design
    9. Graphic artwork development with Photoshop & ImageReady
    10. Database design
    11. Stored procedure development
    12. OO Design and development of middle tier objects
    13. ASP.Net development with C# or VB.Net
    14. .Net desktop application development
    15. JavaScript development & cross browser issues
    16. Ajax/Atlas Development
    17. IIS setup & security issues
    18. Website hosting
    19. E-Commerce development
    20. Conversion of legacy system data
    21. Web Marketing / Search Engine Optimization / SEM
    22. Software Testing & QA
    23. Web based report development
    24. Adobe PDF file generation
    25. Integration with existing systems

    Wide range of Web Development Services we provide:
    We have designed websites of various styles, sizes and purposes. We have a team of 50 Web designers and Developers in our office in INDIA.
    1. Custom Website Design
    2. Template Website Design
    3. Custom E-commerce Design
    4. Website Re-Design
    5. Macromedia Flash Design
    6. Graphic Design

    Wide range of Network Support / System Administration Services we provide:
    1. Onsite server support (upgrades, security patches, migrations)
    2. Remote management and administration
    3. Configure and maintain Windows 2000, 2003 servers and services (Active Directory, DHCP, DNS, IIS, RAS, NAT, VPN )
    4. Install, configure and Maintain Microsoft ISA 2004 server
    5. Installing & Administrating, Managing of Domain Controllers.
    6. Installing, Configuring & Administering the following
    7. Microsoft Exchange Servers
    8. Securing your Linux Server with Firewall / Troubleshooting your Linux System
    9. Server installation and configuration
    10. Security analysis and policy development
    11. Firewall firmware upgrades/Firewall policy implementation and management
    12. LAN Administration
    13. Microsoft Certified Systems Engineers (MCSE)
    14. Cisco Certified Network Associate ( CCNA ) ( CCNP)
    15. Network Installation
    16. Network Management
    17. Network Security and quality monitoring
    18. Network Maintenance
    19. Security Firewalls

    Wide range of Java Services we provide:
    1. Web Application Development in Java
    2. Systems Programming in C, C++, VC++, C-Sharp (C#) and Java
    3. Web Hosting services in JSP and Servlets
    4. Web application maintenance like bug fixing and adding new features
    5. Life cycle testing for web based application and client server products
    6. J2EE Design Patterns
    7. Design and development of applications on J2EE compliant framework
    8. Projects related to Java CORBA and Java XML

    Wide range of Delphi Services we provide:
    1. Delphi application re-engineering
    2. Delphi application development
    3. Delphi .net development
    4. Delphi 7 development
    5. Delphi 2006 development
    6. Delphi 6 development
    7. Delphi application maintenance
    8. Delphi 5 development

    Our reputation for service is second to none, and our entire staff stands ready to work with you and your staff in any way we can be of assistance.

    Eagerly looking for your update…

    Imran Ahmed
    Business Development Manager

    CAT Technology Inc
    ” Committed to Human Excellence Through IT ”

    Phone: 201 255 0319 x 224

    Visit us at—
    http://www.cattechnologies.com

    Note: We respect your on-line privacy. This is not an unsolicited mail.Under Bill 1618 Title III passed by the 105th US Congress this mail cannot be considered Spam as long as we include contact information and a method to be removed from our mailing list. If you are not interested in receiving our e-mails then please reply with a “REMOVE” to Mohammed.Masood@cattechnologies.com in the subject line. I am sorry for the inconvenience caused to you.

  • Daryn

    MVP is a wonderful design pattern.
    Thanks for this great post.

    I have the following questions:

    How can you use the MVP when creating a wizard type interface?
    I want the user to be able to click ‘next’ then the current triad changes to the next triad, and updates the view. I have an implementation, but it does not seem that ‘clean’.

    1. So how do you change triads/views?

    In MVC a model could have multiple views. As far as my understanding of MVP, each presenter has no more than one view – a model can have multiple presenters.

    2. Are these thoughts correct?

    Thank you!

  • http://codebetter.com/blogs/jeremy.miller jmiller

    Don,

    As far as I know, the UIP is effectively dead.

    Jeremy

  • Don Cameron

    Jeremey, nice work.

    It is working well, but I am having a bit of conceptual struggle implementing the User Interface Application Block with MVP. The UIP maintains state in the controller, and has a single controller per business thread, or business group. Any work done in this area?

    Don

    P.S. As for MK: I would like to see critics like this post their work on the net for all to see. I really detest people who pick at little wrong things in light of all this good.

  • jmiller

    Um, MK –

    Can you say “contrived example?” I cut it out of the example in the page for brevity, but I simply used a second constructor that only takes in an IWorkItemView and constructs the default instance of the IWorkItemService.

  • mk

    some people pull their code out of their asses , if you want to be smart
    make sure your code compiles first. If not you’re not differnet than M$ developers.

    –constructor, class WorkItemPresenter
    public WorkItemPresenter(IWorkItemView view, IWorkItemService service)

    –class WorkItemPage
    WorkItemPresenter presenter = new WorkItemPresenter(workEntryControl);

  • Amy Baker

    Questions:
    1. How does MVP handle validation when using the built in .Net validators? Custom validators? Is the presenter involved in that at all or does the view take care of everything? It would be nice to have the validation be testable through the presenter, but it may have to be done through the View.

    2. General question: How to build up text in the presenter to give to the view if the text varies along many different concepts. Example: Simple heading text. We have an inordinate amount of variation in the text for a heading. There are 4 words in our heading. What to display for each word varies on a different concept. You could either have a lot of if statements in your presenter, or have your presenter contain strategies for each different concept and build up the heading that way. Using the strategies seems like better OO design, but almost seems overkill and seems like it would be hard to maintain. Any suggestions?

    3. How do you handle variations in layout? If one layout has three columns, 4 rows and another has 2 colums, 3 rows, do you make a second ascx and code behind even though 90% of the layout is the same? Or does the presenter set a LayoutState on the view and the view then writes out the appropriate html from the code behind based on that LayoutState? I don’t like making a second view that has so much duplication, but I also don’t like writing out html from the code behind. Any ideas?

  • http://www.geekswithblogs.com/billy Billy McCafferty

    Awesome awesome awesome…thank you!

    ASP.NET MVC has been a perplexing problem…this tackles it wonderfully.

  • http://alexfurman.net Alex

    Look at SWExplorerAutomation
    (http://home.comcast.net/~furmana/SWIEAutomation.htm). The program creates automation API for any Web application based on HTML and DHTML The API is used to visually record the test scripts.

    Example links:

    1) Testing your web UI using SWExplorerAutomation and
    NUnit:http://www.testingreflections.com/node/view/2763

    2)Automating Web UI testing with SWEA, C#, & NUnit (part
    http://qainsight.net/PermaLink,guid,de5297ad-53de-4a9d-a78f-bb580afefb5b.aspx

  • matt d

    For unit testing your asp.net apps you might check out RUnit:

    http://www.ruxp.net/runit.asp

    it allows you to run your NUnit tests under the asp.net process.

  • Carlton

    I know this is old, but I just had the time to print this up and read it – I like this article.

    One quick question: isn’t the Presenter in MVP just an expression, or a usage, of a Mediator pattern from GOF? Not that I am knocking your article or MVP, just want to clarify my own understanding. Thank you.

  • Jeremy D. Miller

    Harris & Michael,

    I’ll put out a followup post in the next couple of days to address both questions/objections

    Jeremy

  • Michael

    Jeremy, that was fantasic. I’ve been looking for great MVP examples recently, and that hit the mark.

    A somewhat related question…

    Let’s say I have in coding the Presenter, I’ve created an interface to a back-end service and mocked it, such as you have with the WorkItemService. During this process, the code in the Presenter has come to shpae not only the interface of the service, but the behavior as well, such as expected return values, exceptions, parameter handling, etc.

    Now when it comes time to develop the real implementation of the service interface, there’s always the chance that you don’t exacly recreate the behaviors the Presenter depended on. Maybe you throw throw the wrong exception, or return an empty list in cases where the Presenter was coded against the expectation of null, or some other such quirk.

    How do you either resolve or avoid this?

    Another problem (I’ll just throw stuff out there… comment, blog about it, ignore it… 😉 is dependencies. Do you ever find that excessive constructor dependencies becomes a problem in cases where the Presenter takes a service, and the service takes a data gateway, and the gateway takes a session manager, and the session manager takes a cache manager, etc. That’s just a contrived example, but you get the idea. Essentially, because the dependencies must be injected for the benefit of TDD, you’re now faced with top-level objects having to build a cache manager to build a session manager to build a gateway to build a service, when all it really cares about is the service interface. Do you just ignore it and rely on DI container config files to do it for you, or are there other techniques, or am I missing something and this never happens?

    Anyway, thanks for everything, and keep blogging!

    Michael

  • http://hrboyceiii.blogspot.com Harris

    Jeremy,

    Great post!! I really like how you incorporated the presenter into UserControls.

    One comment I have is related to the interface of the view. A collegue of mine didn’t like the fact that by “exposing” the Model thru the View (i.e., your WorkItem { get; } property), your no longer decoupling the view from the model; or, otherwise put, the UI now knows about the model and if the the UI isn’t supposed to know intimate, inner workings/knowledge of the model. I tend to agree with him, but it leads to coarser View interfaces unfortunately…I guess it’s all a balancing act…

    Great post, again, regardless.

    H

  • cs

    “A lot of .Net literature describes the “Code-Behind” class as the MVC controller. I think this is dead wrong. The code-behind is View code, period.”

    I keep telling people that ASP.Net’s MVC claims are mostly junk. You’re posts are always awesome. Where do you work anyway? Sounds like an awesome place.

  • Liang

    Excellent! Excellent!!
    I definitely need to look at StructureMap to find out how to set up stub. I am using MVP in my projects. But I still haven’t found a goog way to test ASP.NET page. By the way, we should do our validation on presenter or domain layer as well as on presentation layer, since presenter or domain can be used for WinForm as well. so that they have to encapsulate their own logic.

  • http://substantiality.net Sam

    >> “The code-behind is View code, period.”

    Amen. EXCELLENT post.