WCSF Application Architecture 3: Model View Presenter


This article is part of a series;


·         WCSF Application Architecture 1: Introduction


·         WCSF Application Architecture 2: Application Controller


Model View Presenter


The MVP pattern is effectively an evolution of Model View Controller, and is mainly geared at improving the structure and testability of User Interface code. There is a good article here that discusses UI patterns, and a previous post of mine that contrasts the MVP pattern with a pre-release version of the ASP.NET MVC Framework. The Web Client Software Factory (WCSF) uses the MVP pattern, and relies on Dependency Injection to wire up the class dependencies.


The following diagram should help you visualise how MVP is put together;


MVP


 


Note that each Presenter has exactly one View, and each View has exactly one Presenter. There is one Model for the whole application (ahem, see later posts on modularity J).


Let’s consider each item in turn.


 


Model


The model is often misunderstood. It sounds like it should just be data, but then where does my business logic sit? Well, I see the model as representing the whole of my business logic – entities, workflows, and components. It is the window into the real non-UI part of my application. Sticking to our standard architecture defined in the introduction post, the model should only expose business logic components. It should not surface data access components, web service proxies, or other private classes that are further down the architecture stack.


Note that in much of the WCSF documentation the “Model” in MVP is silent – mainly because you could argue it isn’t really a key part to the structure of the UI code, as it is business logic. Hence you might see MVP referred to as “the View-Presenter pattern”. It’s the same thing…


We will discuss the model, how to structure it, and how to implement it in later posts, but for now just think of it as a bunch of plain old .NET objects that “do business logic”.


 


View


A view is used to display data to the user, and therefore in the WCSF is an ASP.NET “aspx” page and its code behind. In the WCSF, this aspx page must implement an interface (e.g. “IHomePage” would define the Home Page view, “HomePage.aspx” would implement it, and it would have a matching presenter named “HomePagePresenter”). The code that exists in this class should be very simple – and should be focussed on two simple tasks;


1.       Taking instructions from the Presenter and converting them into ASP.NET calls.


2.       Taking events from the user (such as button clicks) and passing them on to the Presenter to field.


Effectively, the view is responsible for translating between the Presenter and ASP.NET concepts.


Note that on the pattern diagram above I really wish I could remove the arrow from the view to the model. This is because when I use MVP I enforce a rule that the View should under no circumstances call directly to the business logic. The only reason the arrow is there is because the view may have read-only access to some business entities for rendering purposes only. This is heading towards the “supervising controller” variant of the pattern described in the WCSF documentation here, which I find to be the only practical way to implement data-binding.


 


Presenter


A presenter instructs a view what should be displayed and when, and responds to events raised by the view. It should be unaware of ASP.NET concepts. It should also be the class that interacts with the business logic, potentially passing on single or multiple business entities to the view for rendering. In other words, it is the go-between for business logic and rendered UI.


In the WCSF the presenter has a reference to the view as defined by an interface, hence the two-stage and dotted link in the diagram above.


 


An example


So after all this theoretical talk, let’s see a really simple example of a Model-View-Presenter trio and how they work. Have a look at the following (simplified for clarity) code.


interface IMyView


{


    void DisplayText(string name);


}


 


class MyView : IMyView


{


    public MyViewPresenter Presenter { get; set };


 


    public void DisplayText(string name)


    {


        TextBox1.Text = name;


    }


 


    public void ExitButton_Clicked(object sender, EventArgs e)


    {


        Presenter.OnExit(Page.User.Identity.Name);


    }


}


 


class MyViewPresenter : Presenter<IMyView>


{


    void ViewLoaded()


    {


        View.DisplayText(“Welcome”);


    }


 


    void OnExit(string username)


    {


        BusinessLogic.ExitUser(username);


        View.DisplayText(“You clicked Exit!”);


    }


}


What we have here is the following;


1.       An interface that defines the operations that our View exposes (just “DisplayText” in this case).


2.       An implementation of the view (aspx mark-up omitted in this example). This receives instructions such as “DisplayText” and translates them into ASP.NET concepts – such as setting the Text property on a TextBox.


3.       A presenter, which instructs the View what to do during initialisation, and responds to View events (such as Exit). Note that the Exit method calls into business logic and then updates the view.


I hope that is a nice clear simple example of the interaction between the classes.


 


How do I get my data?


This example contains a really interesting yet subtle point, and that is how to pass data from a view “up” to the presenter. In my code, I make the following call;


Presenter.OnExit(Page.User.Identity.Name);


What this means is that my view is responsible for collecting the relevant data and passing it on to the presenter at the appropriate time. Now this isn’t necessarily wrong, and in many cases is the easiest way to write code – but actually I think it is sub-optimal.


The issue is that we already have an interface defining what our view provides, and I feel that this should really be the contract between presenter and view for as much information as possible. Therefore, I would prefer the following implementation;


interface IMyView


{


    void DisplayText(string name);


    string CurrentUsername { get; }


}


 


class MyView : IMyView


{


    public MyViewPresenter Presenter { get; set };


 


    public void DisplayText(string name)


    {


        TextBox1.Text = name;


    }


 


    public void ExitButton_Clicked(object sender, EventArgs e)


    {


        Presenter.OnExit();


    }


 


    public string CurrentUsername


    {


        get


        {


            return Page.User.Identity.Name;


        }


    }


 


}


 


class MyViewPresenter : Presenter<IMyView>


{


    void ViewLoaded()


    {


        View.DisplayText(“Welcome”);


    }


 


    void OnExit()


    {


        BusinessLogic.ExitUser(View.CurrentUsername);


        View.DisplayText(“You clicked Exit!”);


    }


}


(note: changes are in italic)


What I’ve done here instead is expose the user’s login name as a property on the view, which is defined in the interface that serves as the “contract” between the presenter and the view. I then just raise the “OnExit” event from the view to the presenter, and it is the presenter’s responsibility to extract the information it needs from the view.


This example uses the username, but I would also use it for passing the contents of a textbox edited by the user through to the presenter – expose a property on the view that the presenter extracts the required text from when needed.


I personally think this is more elegant, plus I find it actually helps when writing unit tests. What do you think?


 


MVP + Application Controller


The final point to make is where the interaction with an Application Controller fits in. Hopefully the diagram below helps;


MVP plus AC


I believe that, if you go with my preferred approach to the pattern described in a previous post, the presenter should be the only point of interaction with the Application Controller. So in my simple example above, you might have code that looks like this;


class MyViewPresenter : Presenter<IMyView>


{


    void ViewLoaded()


    {


        View.DisplayText(“Welcome”);


    }


 


    void OnExit()


    {


        BusinessLogic.ExitUser(View.CurrentUsername);


        ApplicationController.CompleteExit();


    }


}


The CompleteExit method would more than likely redirect the user to the home page.


 


Summary


MVP is subject to less confusion once you have ironed out what an Application Controller does, but there are some key points to remember;


1.       There should be no logic other than simple data binding or property access in a View.


2.       There should be no ASP.NET concepts in a Presenter or the Model.


3.       The View must not directly call Model (business logic) methods, but may have a reference to business entities to simplify rendering and data binding.


4.       The Presenter should orchestrate the relationship between the View and the Model (business logic).


Following these guidelines should help enable you to unit test your presenters effectively, and should make you smile when you have to make a change to the code… meaning you know exactly where and how to make that change.


Keep listening to hear about modularity in the WCSF, and as always – chip in if you agree, disagree, or don’t think I’ve explained something sufficiently…


 

Comments (22)

  1. This article is part of a series; · WCSF Application Architecture 1: Introduction · WCSF Application

  2. This article is part of a series; · WCSF Application Architecture 1: Introduction · WCSF Application

  3. This article is part of a series; · WCSF Application Architecture 1: Introduction · WCSF Application

  4. Rainer Bernhard says:

    Until now, I had problems in understanding the m-v-p Pattern, especially in combination with the controllers. The roles of each element (model, view, presenter and controller) and the communication between the elements are clear now.

    One question remains for me: Where do you manage flow and states?

    I came up with the following scenarios:

    1. use case flow and states:

    The place to manage use case states is the controller.  E.g. the Create Order Use Case has several steps: Search Product, Select Product, Enter Customer Data, Submit, Approve, ShowConfirmation…

    The controller nows, in which state the user is.

    2. internal view flow and state:

    A view can provide different actions. E.g. a list can be sorted, filtered,…This does not result in a different use case state. In this case, the presenter is responsible for handling the state and the flow of action. E.g. the presenter holds the Customer-Array, sorts it and forces the view to display the sorted list.

    3. Cross use case flow and states:

    What might be interesting is: How do you deal with use cases that call sub use cases and then continue? Or use cases that call sub use cases as modal dialog. E.g. the "Create Order Use Case" calls the "Select Customer" use case in a modal dialog.

    There is the  Page Flow Application Blog, which I haven’t digged into yet. As I understand it, it is used for scenario 1 (handling use case flow). But what about scenario 3?

    I am really interested in any kinds of thoughts and solutions…

    Rainer

  5. simonince says:

    Interesting comments again!

    I agree with your first and second points – these are really the difference between the presenter orchestrating the "presentation logic" for a view (your point 2), and an application controller managing the flow between views (your point 1).

    For the 3rd point, I think there are a few points to note;

    a) I often find navigation between Use Cases is a manual thing; so a user chooses to register by clicking the "Register" link, or to initiate the checkout process by clicking "Checkout". These links can be created by a module during initalization (to be added to the site map). This means often you need very little cross- use case navigation.

    b) If you’ve seen my post here – http://blogs.msdn.com/simonince/archive/2008/06/19/wcsf-application-architecture-5-defining-modules.aspx – you might have read "7: My Application Controllers are too complex". Here I recommend adding controllers as you see appropriate; enabling you to have a controller per use case if required.

    c) I do hint at needing to think about state that is shared across multiple Use Cases in the above 5th installment too. I would generally recommend centralising your state management if you have a reasonable amount of state (although I would also recommend you don’t have too much state!).

    … I think all this boils down to a vague answer for your point 3! I would probably create another controller that manages cross- use case navigation when required. However, I would by convention only call this controller from other controllers. So my "CreateOrderController" might have a constructor and method like this;

    public CreateOrderController(

      [CreateNew] SelectCustomerController selectCustomerController )

    {

      _selectCustomerController = selectCustomerController;

    }

    public void MyMethod()

    {

      _selectCustomerController.Start( UseCases.CreateOrder );

    }

    … which in turn navigates the user to the start of the select customer use case. You would then likely need to pay attention to which use case initiated the Select Customer use case to decide which controller to resume to afterwards.

    What you’re basically doing here is creating a framework to surround "reusable use cases", which likely cannot be used in isolation. It is not something I’ve ever had to do in the real world, although I have thought about it a little as I’m sure you can see!

    What I have ended up doing instead is embedding reusable User Controls into views to get this kind of reuse. So for example, Select Customer might well be a very very simple search text box and result list; create a user control to host this and you can reuse this "use case" really easily without worrying too much about inter-view and cross- use case navigation; the presenter just manages the interaction within the host view. Of course, the User Control has it’s own View/Presenter pair too, so we’re not breaking from the MVP pattern.

    Hope that makes sense – not a complete prescriptive or real-world proven answer so if you come up with a way you think works let me know.

    Regarding the Page Flow application block, I tend to think of this as an optional way to implement an Application Controller; so the controller effectively acts as a facade to the page flow workflow. This means I wouldn’t tend to worry too much about it’s effect on my application design. Having said that, I have not used the page flow app block for a live deployment myself, so I would probably ask someone else for more real world thoughts on this – I know Paulo Morgado (http://msmvps.com/blogs/paulomorgado/) has blogged on Page Flow quite a lot so could be worth giving his blog a tickle 🙂  Let me know what he has to say if you do.

    Hope that helps!

    Simon

  6. Hi Rainer and Simon.

    The Page Flow Aplication Block was not built to handle sub-flows. It can only handle 1 flow at a time and it will only allow one running instance of each page flow type.

    There are a number of things you can do to change this.

    1. The main obstacle to the use of multiple page flows is the correlation token being stored in a cookie. If you change this behavior to store it in an hidden field (either by forcing the use of a base page or changing the Page Flow HTTP Module to force one in the page). With the new ability to run simultaneous page flows, you can have a service where you register the URL these client side services and keep page flows decoupled.

    2. Another way is using virtual path providers or a router (like the MVC router) to virtualize all navigations in the page flows. This allows different page flows to share pages and you can copy and paste this sub flows into the page flows. Because now you have forked the navigation you can no longer have a single current page. You’ll need to create the concept of paths in the same page flow.

    Like Simon, I haven’t used in the Page Flow Application Block in live deployments myself. But I have built a similar one adapted to y company’s needs using the second approach.

  7. This article is part of a series; · WCSF Application Architecture 1: Introduction · WCSF Application

  8. Preguntas como por que se colocan las propiedades en la interfase de la vista, que debe de ir en el Application

  9. sabb0ur says:

    Hello,

    I really liked this article but I have a question to ask. Where I work, we modified this WCSF MVP approach a bit.

    Instead of the View calling Presenter.OnExit(), the view would fire an OnExit event that is subsequently handled by the Presenter without the View actually calling a method implemented in the presenter.

    I don’t like the approach that we are taking. Do you feel that it has any justtified merits or does it only add more complications?

  10. paulo.morgado says:

    I think it really depends on how many views are calling Presenter.OnExit(). If Presenter.OnExit() is always (or most of the times) called, I think that was a bad idea.

  11. simonince says:

    @ sabb0ur;

    Interesting, and I actually quite like the event driven approach – it fits very closely with how I like to work (in that the View just passes on events to the Presenter).

    I haven’t used *real* events in the past because I thought there might be issues with subscribing to the events at the right time. When do you add event handlers to the view? A few possibilities spring to mind but I’d be interested to hear how you’ve gotten on with this. I guess my concern is that you won’t have subscribed to an event in time before the View fires it.

    If you’ve got this working, though, I’d personally quite like this model; especially if you’re avoiding passing state in the events and rely on the Presenter inspecting the View’s state as I describe above.

    Hope that helps!

    Simon

  12. Jeff G says:

    I’ve been also working on a similar MVP pattern for ASP.NET. The one thing that I haven’t yet seen discussed much when reading about the WCSF is that it appears like the pattern suggests 1 view per aspx page. I tend to think of using views more like the CAB, where there are multiple (at times) per screen, and that "view presenters" can communicate to other view presenters using an event broker mechanism (but the view communicates with the presenter through standard .net delegate based events). I haven’t yet used this in a real world project, but it seems to work well and seems to be a nice pattern.

     What are other’s thoughts about using multiple views per page in WCSF. Is it designed for this?

  13. simonince says:

    Jeff;

    good question! I think the best way of composing multiple views into a single page is to use User Controls; it keeps it simple, is closely aligned with how ASP.NET works, and WCSF 2.0 supports MVP for User Controls. What I then find is that the "host" page’s Presenter can co-ordinate calls between the User Controls in whatever way it sees fit.

    I have seen other patterns used to orchestrate calls between page components, such as event brokers and/or mediators – but to be honest I just found the complexity and extra work to be over the top. This is a sweeping statement, but I just like to keep things as simple as possible!

    So I guess I’m saying if you’ve gotten it working and it seems fairly simple then it sounds great (and I’d love to see a blogged code sample or something!) – but I’d just caution to avoid over the top complexity.

    Simon

  14. Chris Aniano says:

    Simon,

    Just a clarification on MVP + Application Controller, Using WCSF(VS2008):

    – Web Client Factory > Add Page (with Presenter), this will create dafault.aspx, dafault.aspx.cs & IdefaultView.cs (for it’s View) & defaultPresenter.cs (for it’s Presenter), but where is the Application Controller?

    Does it mean I need to manually create a defaultApplicationController.cs (for it’s Application Controller)?

    If yes, where should i put it? is it the same location as the defaultPresenter.cs?

    Are all Presenter should always have a corresponding Application Controller if where are talking of MVP + Application Controller?

    Thanks,

    Chris

  15. simonince says:

    Chris;

    very good question, I don’t think I’ve mentioned that anywhere!!

    Application Controllers are created by the factory when you create a new *module* – there is by default a single controller per module named MyModuleController.cs in the root of the C# project.

    In general you should have much fewer controllers than views/presenters because they should be managing the flow between views when you have a "page flow" – I’d check out the "what is page flow" section in my application controller post (http://blogs.msdn.com/simonince/archive/2008/06/06/wcsf-application-architecture-2-application-controller.aspx) for more info, as this discusses when you should or should not bother with using a controller in my opinion.

    One thing I do also discuss in my "defining modules" post (http://blogs.msdn.com/simonince/archive/2008/06/19/wcsf-application-architecture-5-defining-modules.aspx) is adding new controllers when appropriate – check out pain point number 7.

    So in other words, the factory adds a single controller for you per module, there should not be a controller per presenter, and if required you can add your own controllers very easily!

    Hope that helps!

    Simon

  16. hongliangqiang says:

    Hi Simon,

    A follow-up on your answer to Jeff’s question:

    Regarding "best way of composing multiple views into a single page is to use User Controls", do you mean just add the component in the standard ASP.net way without presenter?

    I actually have been doing the opposite, i.e. adding User Controls from "Web Client Factory" context menu with presenter. After a while, I found myself left with lots of skeleton presenters for User Controls without much code in it, since the "real" logic almost always needs to be implemented in the host page presenter. While doing this, I also face the choice of whether to make wrapper properties on page view interface around user control view interface properties, or just expose the user control view itself as a property of the host page view interface. The former seems a lot of redundant work, and the latter will violate the LoD, i.e. "only one dot" rule.

    Those issues prompted me to re-study your comments again and it occurred to me maybe that (add the component in the standard ASP.net way without presenter) is what you meant. But then you said "the "host" page’s Presenter can co-ordinate calls between the User Controls", which seems to suggest the User Controls should have some interface in order to be accessible by the host page’s Presenter.

    Thanks a lot,

    Hongliang

  17. simonince says:

    @ Hongliang,

    good questions. Above I did mean the WCSF MVP versions of user controls, but there is more to it than that.

    I think the confusion comes down to there being two main types of controls… Those that contain logic, and are effectively encapsulated system behaviour themselves, and those that are just display controls.

    For example, you might have a User Control that handles displaying a customer record, that formats the output, allows you to edit their address, click a button to view their orders, and flag them as missing payments. This would likely have an MVP pattern behind it, and I think it can be described as a "view".

    You might also have a control that is used purely for rendering – it might be business specific and display a customer address, or be business agnostic and display a numeric-only field that has "up" and "down" buttons next to it. This wouldn’t have an MVP pattern, and isn’t a "view" itself.

    Both of these are valid ways to reuse logic and controls, but only one is a sensible way to compose "views" into multi-view screens (e.g. master-detail screens)… which is the use case I was referring to.

    Does that help?

    Simon

  18. hongliangqiang says:

    Hi Simon,

    Thank you very much for the prompt response. It is most helpful.

    The two main types of User Controls you described are exactly what I have been struggling with. In particular, I found it not always easy to recognize which type my new User Control belongs to.

    For example, I have a panel of search/filter controls including both TextBoxes and DropDownlists as well as a submit button, which I would like to refactor into a separate User Control. This User Control itself does not feel like a complete "View" for me, since its fuction is very simple — collect and send search criteria, and the search result will be shown in another GridView on the page outside the User Control. On the other hand, I do need to contact backend service to both pre-populate the dropdowns and to submit the search request eventually, both of which can be counted as "logic".

    I guess what I am troubled with is the need to decide case-by-case and the architectural impact of any wrong judgement. Furthermore, if I "pollute" an existing display-only user control with business logic, I will need to manually change the base class of the User Control, and create interface and presenter for it, which makes me want to rather create every user control with MVP "just in case".

    Also, I wonder what is the recommended way for the "host" page’s Presenter to co-ordinate calls between the (MVP enabled) User Controls. Since the page presenter can only access the page via its view interface, it looks the User Controls need to be exposed as part of the page view interface. So the question is in which fashion the User Control should be exposed. Should the IUserControlView be added as a (read-only) property of the IPageView, or should the IPageView add some wrapper memebers around the memebers of each of the IUserControlView’s? Or, is it totally out-of-question for the page presenter to directly invoke methods on user control presenters?

    I apologize if above questions are too implementation-specific or too detailed to be relevant to the main topic here. As always, any of your comments would be greatly appreciated.

    Thanks,

    Hongliang

  19. simonince says:

    @ Hongliang

    sorry for the delay – I’ve been putting off responding until I could spend some time on it, but realistically that’s not going to happen at the moment!

    Very briefly…

    1. I think you’re right about it being important to pick the right control type, but on the other hand, refactoring is absolutely fine if you find a better way of doing something… so personally I’d come up with an approach and take it as far as makes sense. Oversimplification I know 🙂

    2. For inter-view communication it depends on your needs, but I see nothing wrong with just using events exposed by a control and consumed by another. This means you are basically treating them as controls – which they are! If the communications are more detailed than this, though, you end up with quite a complex chain of chain of calls through pages, views, and presenters. I’ve not done this for quite a long time hence I wanted to try it again, and write a sample, but no time I’m afraid! Bottom line is, I’d avoid anything too complex if I were you, as it quickly becomes a pain.

    HTH

    Simon

  20. Ganesh says:

    Thanks for the nice blog/ article. Really helped me understand my appln which also follow MVP arch.

  21. JRose22 says:

    @ Simon and Hongliang

    I know this post is quite old, but I am in the exact same situation that Hongliang has described. I think the biggest difference is that I am developing WinForms applications, but the pattern applies the same.

    I have searched for a few days now, reading many posts/blogs, but still have yet to read (or better yet, see!) that one piece of information that allows it all to "click" for me.

    I too love to use UserControls as much as possible, but as soon as I add a 2nd UserControl to my form it seems that my brain just shuts down on what to do next.

    I have recently written an application that contained 5 UserControls (each using the MVP Pattern).

    One UserControl was for displaying a list of objects held within a collection.

    One UserControl displayed the details of the selected object from the first UserControl.

    Another UserControl had actions that could be performed on the selected object from the first UserControl and so on.

    This was not for work but for my desire to learn the pattern. So I read a few post, watched a video or two, and then jumped into coding. I quickly found myself with 5 UserControls on the same WinFrom, without any clue as how these UserControls would interact with each other.

    What I ended up doing in the end was exposing the UserControl Interfaces with the main form’s Interface.

    public interface IMainFormView

    {

     IUserControl1 {get;}

     IUserControl2 {get;}

     …

    }

    In the main form’s presenter I subscribed to the events of the UserControls and reacted appropriately. However, this was not a very elegant (or simple) task for me. I even made it worse by passing in the collection to each of the UserControl’s presenters so that they could hook up to the events when the collection changed! Argh!

    I have since realized that maybe I should adopt the App Controller pattern to my application. Immediately I ran into the same problem, except now, I don’t know how to get the controls to react to the App Controller lol.

    That’s when I decided to hit the web again. This post is probably the best one that I’ve come across that someone else has explained my exact situation. It’s nice to know I’m not alone, even if it means someone else is suffering lol!

    I would love any response/advice that anyone could give me on this subject.

    I would also like to end with my appreciation to those people who make an active effort to create posts like these. Hopefully one day, I can return to favor.

  22. simonince says:

    @ JRose22;

    Have you seen "Prism" (or Composite WPF as it’s known)? It is focused on WPF rather than winforms but they discuss UI composition in it quite well;

    http://compositewpf.codeplex.com/

    Fundamentally this question is very hard to answer in Web Forms, but in WPF and WinForms it gets a bit easier. Also in MVC there are more options (just see the Web App Guidance from p&p that uses similar principles to Prism; http://webclientguidance.codeplex.com/).

    Basically it sounds like you’re after "Top Down Composition" (or "View Discovery", so go check that out in their docs and it should help! I’ve heard that some people have ported Prism to WinForms but even without that the concepts should be useful.

    The Prism UI composition docs are here;

    http://msdn.microsoft.com/en-us/library/ff648265.aspx

    Hope that helps.

    Simon