Geeks With Blogs
Billy McCafferty whatever (but really just .NET)

On a previous post, I mentioned my introduction to Model-View-Presenter (MVP).  I've now gotten a chance to try it out on a new project and have been very pleased with the results thus far.  MVP provides an approach for clean separation of concerns within the ASP.NET presentation layer without dismissing the page event model.  MVP sees the code-behind, along with the ASPX page, as strictly part of the view and provides a patter to treat it accordingly.  Although the pattern itself is easy to understand after looking at an example, I expect it'll be another couple of years before strong MVP “best practices” emerge.  (I was surprised to find that MVP was actually conceived over ten years ago by IBM's Taligent and put to the test on Dolphin Smalltalk.  Even though it's been around for a while, it didn't get any substantial attention unitl recently with Martin Fowler's inclusion of MVP in his upcoming book.)

I'd like to put forth some rules of thumb for using MVP with ASP.NET that I've learned from a number of other sources and recent personal experiences.  These are very open to criticism...in fact, I encourage it!  By no means do I deliever these as true best practices of MVP - I hope to get as much feedback as possible concerning your own experiences and the applicability of these tips.  (I have not provided much with respect to MVP code samples since your favorite search engine can find you plenty.  The links below contain samples as well.)

MVP Tips:

  • Calls from the presenter back to the view should resolve to simple accessors; the accessors should only accept/return model objects or primitives - business objects, data transfer objects, datasets, etc.  (http://codebetter.com/blogs/jeremy.miller/archive/2006/02/01/137457.aspx)
  • The presenter constructor should accept the view it presents along with any services it may depend on (i.e. dependency injection).  The following example serves to illustrates:

private readonly IEditCommentView view;
private readonly ICommentDao commentDao;

public EditCommentPresenter(IEditCommentView view, ICommentDao commentDao) {
  this.view = view;
  this.commentDao = commentDao;
}

  • The presenter should never require a reference to System.Web.
  • Don't expose too much of how the view is implemented via its interface.  For instance, examine the following code...

public bool IsClassical {
  get { … }
  set {
    chkClassical.Checked = value;
    txtComposer.Enabled = value;
  }
}

In the above example, you could instead provide two setters on the view:  IsClassical and ComposerEnabled.  The downside to having two setters is that you've bound a very minor implmenation detail to the interface - arguably, you should be able to easily switch concrete views and have presentation variations among them all.  The counter-point is that the view should remain completely ignorant of business decisions and should leave all details up to the presenter; therefore, the view should have two setters:  IsClassical and ComposerEnabled.  Additionally, giving ComposerEnabled its own setter allows it to be disabled for security reasons; regardless of the other settings.  (This example and discussion was brought up at http://codebetter.com/blogs/ben.reichelt/archive/2005/11/18/learning_model_view_presenter.aspx.)  Personally, I've found the single setter to be cleaner and promotes a more cohesive interface.

  • It's common practice to partition the GUI into separate user controls for proper separation of concerns and maintainability.  An effect of this is that it becomes easy to define the view/presenter relationship from the code-behind of the containing ASPX page.  The following example illustrates the parent page determining this relationship between a contained usercontrol (i.e. the view defined as commentListing), and the usercontrol's presenter (ListCommentsPresenter):

ListCommentsPresenter presenter = new ListCommentsPresenter(commentListing, DaoFactory.GetCommentDao());
commentListing.AttachPresenter(presenter);

if (!IsPostBack) {
  presenter.Init();
}

The call to AttachPresenter binds the presenter to a private member within the user control.  With this approach, the usercontrol never has to know how to create the presenter nor need knowledge of the constructor arguments that go along with the presenter's creation.  Finally, the usercontrol doesn't have to worry about when to call Init.  (This implementation tip comes from http://codebetter.com/blogs/jeremy.miller/archive/2006/02/01/137457.aspx.)

  • Views should provide a DisplayMessage property to the presenter so as to return feedback concerning the execution of an operation.  Alternatively, the presenter could return a “presenter result“ object to indicate what should happen next:  redirect, stay on the page, go to login, etc.  (This latter tip came from Mike Mason's blog that's accessible via Google cache.)
  • Unit tests should be used for guiding the communications protocol between a view and presenter.  Implementing the view itself should always be the last thing you do - NUnit and FitNesse can be used to validate most of the presentation before writing a scratch of HTML.  The primary benefit of this is ensuring you've done a good job of cleanly separating all possible business logic out of the view.

There are certainly other topics of discussion concerning MVP, but the above should be a good start with respect to “better“ MVP practices.  Please send feedback, comments and criticisms my way!

Billy

Posted on Thursday, March 30, 2006 1:59 PM ASP.NET , C# , Model-View-Presenter | Back to top


Comments on this post: Journeys with Model-View-Presenter and ASP.NET

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
Nice post, however you can simply pass 'this' into the constructor for the view.
Left by Nick Parker on Apr 17, 2006 5:49 PM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
Hey Nick, thanks for the comment. I assume you're talking about the snippet

<pre>
ListCommentsPresenter presenter = new ListCommentsPresenter(commentListing, DaoFactory.GetCommentDao());
commentListing.AttachPresenter(presenter);

if (!IsPostBack) {
presenter.Init();
}
</pre>

In this example, <code>commentListing</code> is a UserControl and the code shown above is found within the code-behind of an ASPX. So in essence, the ASPX code-behind acts as the "wiring initializer" between its constituent user controls and the presenters that work with the user controls. What are your thoughts on this? Do you feel the user controls should be creating their own presenters and call Init within their own Page_Load? I'm not sure what the answer is besides "it depends." In some cases, I could see why you'd want the ASPX page to do the wiring if the user-controls settings change based on the page it's being used in. Otherwise, it could be wired within the user control itself if the settings don't vary by page. But overall, I lean a bit towards the ASPX page doing the initialization-wiring to follow a more dependency-injection approach. But then again, perhaps its 6 of one, 1/2 dozen of another. ;)

Billy
Left by Billy McCafferty on Apr 18, 2006 6:39 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
Billy,
Thanks for clarifying the code; I was under the impression that your commentListing represented the Page. In my opinion, separating the view to individual user controls is fine until your application requires you to integrate several views (i.e., user controls all on one page). The problem I see with this is we end up with a Page acting as a container for several views and a presenter(s) that needs to handle that which could become a maintenance issue down the road (the coupling could be simply be refactored to a single view/presenter). I'm curious about your thoughts on this. I’m looking forward to reading more of your posts.
Left by Nick Parker on Apr 21, 2006 5:30 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
In my current project, a bit experimentally, I've tried to take a strict approach of putting every view into a user control and keeping ASPX pages as containers and dependency injectors.

For instance, on a comment listing page, the ASPX could have two user controls: a usercontrol to show comments in a table listing, and a usercontrol to show an edit-comment form. (Arguably, both of these pieces of functionality could be put into the same control.) Now with this example, the ASPX is responsible for creating presenters, passing the views (usercontrols) to the presenters, creating/giving service dependencies to the presenters, and calling presenter.InitView. The ASPX page takes care of one other thing, handling events raised by the usercontrols for navigational purposes...

Assume you'd like to reuse the edit-comment view/control on multiple pages. How do you know what page to redirect to when the user clicks cancel on the usercontrol? (Assume you're not using a front controller.) The way I've been doing it is raising a Cancel event from the user control and having the ASPX page capture and handle the event. That way, you could reuse the control on different pages without having to embed any navigational functionality into the control itself.

A tenant of OOP is high-cohesion; taking this to the presentation level means keeping each ASPX and ASCX as cohesive as possible. So, in the discussed example, ASPX pages handle view-presenter initialization and flow. ASCX usercontrols handle displaying the model (given to it by the presenter) and passing UI-events back to the presenter (via method calls) or back to the ASPX page (as an event) if it's navigation related, such as "Cancel."

I've found this strict approach can be a bit overkill if an ASPX page only contains one usercontrol, but it shines when you have to add another usercontrol to the same page. IMO, the ASPX page remains cohesive and, besides initializing, stays cleanly out of the affairs of the view-presenter relationship.

I'd love to hear your opinion on this as I'm still trying to make up my mind as to "where the boundaries" should lie and present my ideas humbly.

Billy
Left by Billy McCafferty on Apr 21, 2006 9:04 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
My concern with putting multiple Views/Presenters on a page is that I would be introducing business logic within my Page class to identify which View/Presenter to instantiate and when. Maybe this is something you've already addressed?
Left by Nick Parker on Apr 21, 2006 11:24 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
That's certainly a issue worth discussing. Who should be responsible for collating controls, and creating/injecting dependencies? In my current project, I've given all of these jobs to the ASPX code-behind. It's worked alright but one of the major benefits of MVP is being able to treat code-behind pages as strictly part of the presentation and not part of business logic...which is something arguably violated by my approach. An IoC container, such as Castle Windsor, could be enlisted to take care of the dependency creation, but that would still leave collating the usercontrols and navigational control to the ASPX code-behind that houses the usercontrols.

My next step will be to see how much Castle Windsor may alleviate the ASPX code-behind of some of these responsibilities. Besides this, what are your thoughts on navigational control...do you use Front Controller or something similar? I've been using PageMethods which strongly-types redirection; thus, greatly simplifying navigation...but I still have redirects within the ASPX code-behinds which brings along with it plenty of pros and cons.
Left by Billy McCafferty on Apr 21, 2006 11:45 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
Your posts have been great, thank you!

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?
Left by Amy Baker on Jun 01, 2006 10:02 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
Thanks for the positive feedback! In response to...

1) I use PeterBlum.com validators to take care of client side validation for their flexibility and lack of JavaScript that I end up writing. I then pass Page.IsPostBack and Page.IsValid to the presenter - this allows the presenter to decide what to do depending on the state of these flags instead of leaving it up to the view. In this way you can at least test "all or nothing" validation based on Page.IsValid, but you'd still have to test fine grained validation on the view; albeit, you could use something like http://nunitasp.sourceforge.net to unit test the client side validation as well. Personally, I find NUnitASP mostly useful for just nightly "smoke tests" - I end up testing the view's validators manually.

2) Could you give a little more detail on what a "concept" is and a more concrete example of how the heading text would change in different conditions?

3) I encounter this situation often. In the typical situation that I encounter, I want to show/hide a column/row based on a permission setting. E.g. the "admin" should see an "Edit" column and should see an "Add New" footer. In this case, I expose a property on the view called, for example, "EnableAdminCapabilities." The setter would then show/hide the necessary columns/rows. Here's what it would look like:

public bool EnableAdminCapabilities {
set {
myGrid.Columns[myGrid.Columns.Count].Visible = value;
}
}

Arguably, this is giving the view some logic handling. But on the other hand, I see this particular example as an implementation detail of the view which does not concern the presenter. In this way, the same presenter could be used with different views and not care what effect EnableAdminCapabilities will have, only on whether or not it should be set to true.

As soon as I get a little time, I'm trying to put togehter a more comprehensive article concerning MVP and the different approaches that can be used; for instance, pure ASPX vs. the ASPX/ASCX combo. I'll add a post when it's complete.

Hope this helps.

Billy
Left by Billy on Jun 01, 2006 10:26 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
Thank you for the feedback!

1. More detail on my item #2:
Example: It is a website used to make airline reservations. The title of one page is "Confirmation - Held Award Reservation". Each word varies according to a different concept. "Confirmation" can be "Confirmation" or "" depending on the process step the user just completed, e.g. if they just purchased, show "Confirmation", if they are viewing an old reservation, show "". The word "Held" can be "Held" or "Purchased" depending on the state of the reservation. The word "Award" can be "Award", "Standard", "ECertificate" depending on the fare type of the reservation. The word "Reservation" is the same for all scenarios.

Question: We could either have a lot of if statements in our presenter to build up this text, or have our 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?

2.
Example: If you had a bit of text such as the following: "The little brown dog jumps over the moon." Let's say the word "brown" is a hyperlink to somewhere and could be either brown or green depending on biz rules. Lets also say the word "jumps" can be jumps or leaps and if it is leaps it must be bold. (This is not just an exercise, we do have requirements this complex that we are trying to figure out).

Question: Do you build up the text in the presenter and set it on the view so you can write a unit test to verify the text? Or do you set properties on the view like DogColor and DogAction and then have the view piece the text all together? If you opted to put the logic in the presenter, the presenter is now building up a hyperlink and inserting the html bold tag in the text it is returning. That doesn't seem quite right either...?

Thanks for your help, we are trying the MVP out on one of our real pages, that is why we are running into scenarios that are not neat and tidy.
Left by Amy Baker on Jun 05, 2006 5:39 PM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
Hi Amy, thanks for the clarification. With response to...

1) I'd lean towards the strategy approach...something requiring a lot of if statement usually requires a lot more if statements down the road. For example, I had a simple search/filter page with only a few filters available. I could have used a bunch of if statements or used the Specification/Interpreter pattern. Although the specification pattern seemed heavy for what I was doing, it paid for itself 10-fold in the long run as the search/filter selections grew from three to six. If I hadn't used the specification pattern, my if statements would have gotten terribly out of control. If you feel there's a possibility that more conditionals may come into play down the road, I'd go the strategy route - it may take a little more up front planning, but it'll pay dividends in the maintenance phase (which is where you're going to spend most of your time anyway).

2) I want to work where you're working! It sounds like you have some fun challenges. ;) Your second question could be approached 100 different ways...which makes it all the more fun. As you mentioned, your options are to have the ASPX page put together the HTML or have the presenter put together the HTML. At first glance, I would feel inclined to have the presenter put it together and then give it to the view via a "public string Message" property. For something as complex as sentence composition, I would definitely want to be able to unit test it with the presenter. Also, if I start letting the ASPX/code-behind be anything more than a dumb view, then the code-behind will probably start taking on other responsibilities as the complexity of the problem grows. But on the flip-side you wouldn't want to hard-code a hyperlink target into the presenter since you'd have to recompile the presenter package if an ASPX page gets renamed. I would create a target lookup table as an XML file that pairs a number of "actions" with their hyperlink targets. For instance, a sample lookup pair could be "BrownAction=~/Web/ListBrownStuff.aspx." You could even pass the action/target pairs to the presenter as a Hashtable so the pairing is maintained within the Web layer but still leaves it up to the Presenter layer to handle how it's used. If it's passed to the Presenter layer in this manner, you could modify action/targets without having to recompile the Presenter. (You may want to take a look at the XML config files used for http://mavnet.sourceforge.net as a source of inspiration for how you may want to format your own action/target file.)

Again, there are many ways to implement a solution but it seems like this might present a maintainable way to keep the Presenter ignorant of the Web layer (e.g. there's no hard-coded reference to an ASPX target) while still keeping the Web layer ignorant of how messages should be constructed (e.g. the code behind only exposes a public setter for a message to be composed by the presenter). On a side note, the Builder design pattern may prove useful for composing the sentence itself...but it may also be overkill. ;)

Hope this helps,
Billy
Left by Billy on Jun 07, 2006 9:08 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
I've posted an extensive overview of MVP with ASP.NET at http://www.codeproject.com/useritems/ModelViewPresenter.asp. Your feedback is most welcome.

Billy
Left by Billy on Jul 02, 2006 8:24 PM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
I am an absolute newbie at MVP and struggling to get any example code (pinched from Jeremy D. Millers' site) working especially the AttachPresenter bit? Grateful for any help.
Left by Alex on Jul 05, 2006 8:39 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
Downloading the second example from http://www.codeproject.com/useritems/ModelViewPresenter.asp should get you going in the right direction. Let me know if you need further assistance.

Billy
Left by Billy on Jul 05, 2006 8:45 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
Billy,

Very much appreciated, the example you suggested has really helped although when trying to run the code in VS2003 I am running into issues referencing the user control?

Grateful for your thoughts?


Alex
Left by Alex on Jul 06, 2006 12:25 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
Billy,

Just being particulary slow this morning, its all up and running now, thanks for your help and will be sure to keep an eye on your blog for future updates. Thanks.


Alex
Left by Alex on Jul 06, 2006 1:03 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
I should have made it more clear that it is an ASP.NET 2.0 solution. It will only work in VS 2005.
Left by Billy on Jul 06, 2006 6:11 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
I just now saw your second comment...great! ;)

Billy
Left by Billy on Jul 06, 2006 6:12 AM

# re: Object Datasource control with Model-View-Presenter and ASP.NET
Requesting Gravatar...
Hello - I really like your article & plan to use it my current(new) project.

But I got couple of questions for which I do not have a definite answer. Please do the needful.

1. Without violating MVP principle, would it be possible to use Object DataSource control in an Asp.net page.(because Object datasource binds the business object information at design time).

2. Is Atlas AJAX concept really working well with this architecture?

It would be really helpful, If you could be give me some insights on above topics?

Thanks,
Chandra
Left by Chandra on Oct 09, 2006 9:41 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
Billy,

Thanks for all your great articles, I find them extremely informative.
I am currently working on a project using nHibernate and telerik controls. I am trying to implement MVP however I am having difficulty udnderstanding how Preseneter.InitView() manges to intialise a view from domain object using the appropriate injected DAO. In order for the correct domain object to be intialised the presenter needs to have some initialisation data such as an ID or some or other criteria to perform the fetch through the DAO. Do you simply overload the InitView() method to accept this data or is there a better more suitable way of doing this?
Or am I missing the point here alltogether?
Your help would be hugely appreciated.

Thanks
Stuart
Left by Stuart on Dec 05, 2006 8:06 AM

# re: Journeys with Model-View-Presenter and ASP.NET
Requesting Gravatar...
You're right on the money. On my current project, I'm also using telerik along with MVP. Here's a snippet from a presenter of mine:

public BudgetWorksheetPresenter(IBudgetWorksheetView view, IProjectDao projectDao) {
Check.Require(view != null, "view may not be null");
Check.Require(projectDao != null, "projectDao may not be null");

this.view = view;
this.projectDao = projectDao;
}

public void InitViewFor(long projectId, User userViewing, bool isPostBack) {
...
}

private IBudgetWorksheetView view;
private IProjectDao projectDao;
Left by Billy on Dec 05, 2006 8:27 AM

Your comment:
 (will show your gravatar)


Copyright © Billy McCafferty | Powered by: GeeksWithBlogs.net