Click here to Skip to main content
Click here to Skip to main content

Advancing the Model-View-Presenter Pattern - Fixing the Common Problems

By , 6 Sep 2007
 

Introduction

Before you read this article, make sure you're caught up on Billy McCafferty's article on the MVP pattern. Not only does this article take a large inspiration from Bill's work, but he put a lot of effort into one of the better articles recently posted on The Code Project. Thanks, Billy!

On to the task at hand.

The Problem

Like most emerging patterns, spending even a little time with the MVP pattern reveals both strengths and weaknesses. Billy does well to explain the benefits of keeping the ASP.NET pipeline in tact and the obvious ease of unit testing. One huge benefit not yet addressed is presentation layer reusability (see the sample WinForms app). But for all its benefits, the MVP pattern, as people understand it in its early stages, has its share of problems.

Based on what I see as the public's current understanding of the MVP pattern, let's list a few of the major weaknesses:

  • No Code Reuse - Each view (page/control) must create an instance of a specific presenter in order to invoke the presenter's methods. That's four or five lines of code per page/control; quite a bit of work if you have hundreds of pages and controls in your site. Code can and should be centralized.
  • Presenter Creation - Presenters operate on a specific type of interface. Generally speaking, there's a one-to-one relationship between presenters and interfaces. This problem relates to the "no code reuse" point, and leads to inconsistent public-facing functionality exposed by various presenters. Object creation should be standardized.
  • View Intelligence – Using the MVP pattern forces a view to know as much about its presenter (methods, properties etc…) as the presenter knows about its view. The use of interfaces prevents a circular reference, but there should still be further decoupling of the view. One area I may disagree with Bill is that views should also not know what data layer type (or DAO interface type) to pass to a presenter. I'm of the opinion that the views shouldn't have a reference to any data layer (i.e., anything upstream of the presenters).
  • State Management – This one is a biggie. Many of the people posting on MVP are quick to point out that (very simple) MVP examples remove the ability for ASP.NET to use session and caching. How do you access context-specific information if presenters can't have a reference to anything downstream (i.e., System.Web or System.Windows.Forms)? The presentation layer should provide a way to maintain application state.

The Challenge

Let's tackle each of these problems head on, one-by-one. By the end of this example, we should have the beginnings of a more matured approach to MVP as it applies to .NET.

No Code Reuse: Every single page contains an instance of a presenter. That's quite a bit of copy-paste if you want to convert a large website to use MVP. The obvious place to start is by creating a base class for all presenters that all the views can share. We'll add an abstract base presenter to the presentation project. The constructor takes a generic IView interface and provides a method (via Generics) to cast the view to a more specific interface type. To keep the view's logic as simple as possible, the base presenter will expose a single abstract method, "Execute". Each concrete presenter will be responsible for the implementation details for Execute, but any view can now call Execute without having to know anything about the type of presenter it's calling.

/// <summary>
/// Base functionality all Presenters should support
/// </summary>
public abstract class Presenter
{
    protected readonly IView _view; 
    public Presenter( IView view ) : this(view, null)
    { } 
    public Presenter( IView view, ISessionProvider session )
    {
        _view = view; 
        if(session != null)
        {
            SessionManager.Current = session;
        }
    } 
    /// <summary>
    /// Converts an object from IView to the type of view the Presenter expects
    /// </summary>
    /// <typeparam name="T">Type of view to return (i.e. ILoginView)</typeparam>
    protected T GetView<T>() where T : class, IView
    {
        return _view as T;
    } 
    protected ISessionProvider Session
    {
        get { return SessionManager.Current; }
    }
}

Now that there's a base implementation for the presentation layer, a base web page is in order. We should be able to get rid of those four or five lines of code required by each page and move it to a few lines in the base page. On a site with 300 pages and controls, we just saved 1200 lines of code! In short, the base page provides two methods to facilitate registering a view with the associated presenter.

public class BasePage : System.Web.UI.Page, IView
{
    protected T RegisterView<T>() where T : Presenter
    {
        return PresentationManager.RegisterView<T>(typeof(T), 
           this, new WebSessionProvider());
    }

    protected void SelfRegister(System.Web.UI.Page page)
    {
        if (page != null && page is IView)
        {
            object[] attributes = 
              page.GetType().GetCustomAttributes(typeof(PresenterTypeAttribute), true);

            if (attributes != null && attributes.Length > 0)
            {
              foreach(Attribute viewAttribute in attributes)
              {
                if (viewAttribute is PresenterTypeAttribute)
                {
                   PresentationManager.RegisterView((viewAttribute 
                         as PresenterTypeAttribute).PresenterType, 
                         page as IView, new WebSessionProvider());
                   break;
                }
              }
            }
        }
    }
}

The base page provides two differing ways of view registration. A view can pass in the type of presenter to load, along with an instance of itself, to the RegisterView<T> method. This is really more of a left over convention from the original code this article was based on. The more friendly method of registration is done by a page calling the SelfRegister method and passing itself, as an instance, as the solitary argument. The SelfRegister method then examines the page's attributes to find the correct presenter type to load.

Presenter Creation: Now that the base web page handles calls to the Presentation Manager, there's no reason why presenter creation should be complex. A simple presenter factory would be a clean and easy way to standardize how presenters are created. All we need to know is the type of interface the view implements. That's enough information to create the appropriate presenter.

public static class PresentationManager
{
    public static T RegisterView<T>(Type presenterType, 
                  IView view) where T : Presenter
    {
    return RegisterView<T>(presenterType, view, null);
    }

    public static T RegisterView<T>(Type presenterType, IView view, 
                    ISessionProvider session) where T : Presenter
    {
    return LoadPresenter(presenterType, view, session) as T;
    }

    public static void RegisterView(Type presenterType, IView view)
    {
    RegisterView(presenterType, view, null);
    }

    public static void RegisterView(Type presenterType, 
                  IView view, ISessionProvider session)
    {
    LoadPresenter(presenterType, view, session);
    }

    private static object LoadPresenter(Type presenterType, 
                   IView view, ISessionProvider session)
    {
    int arraySize = session == null ? 1 : 2;
    object[] constructerParams = new object[arraySize];

    constructerParams[0] = view;

    // Add the session as a parameter if it's not null

    if (arraySize.Equals(2))
    {
        constructerParams[1] = session;
    }

    return Activator.CreateInstance(presenterType, constructerParams);

    }
}

For this example, and for simplicity, I put a custom attribute on each view that defines what view interface type it operates on. This makes object creation easy, fast, and a great candidate for caching after the first call. A more complex example or framework may use a custom configuration section for more flexible mapping. This example also doesn't account for mapping multiple presenters to a single view; something that may be necessary for a real MVP framework.

View Intelligence: Our base page class helps to reduce the view's registration logic, but there's more to tidy up to be done. The view doesn't need to know any details of the presenter's methods and properties (remember, no up-stream references). The view only needs to know the operations it wants to perform, and those are defined in the respective interfaces. Let's take the common task of logging in to a system. Before our modifications, the code would look like this:

protected void loginButton_Click( object sender, EventArgs e)
{
    _loginPresenter.LoginUser(this.userNameTextBox.Text, 
    this.passwordTextBox.Text);
}

This isn't bad, but the view has to explicitly give the presenter the requited data. A cleaner approach would be for the view to request a type of execution and let the presenter get the data it needs.

public event EventHandler OnLogin;

protected void Page_Load(object sender, EventArgs e)
{
    base.SelfRegister(this);
}

protected void loginButton_Click( object sender, EventArgs e)
{
    if(this.OnLogin != null)
    {
        OnLogin(this, EventArgs.Empty);
    }
}

Remember that one of the goals of MVP is to truly separate responsibilities. Letting the presenter respond to events fired by the view for data truly puts the responsibility on the presenter to take action. This design also works better for unit testing, because your mock views in your unit test will more closely match your real-world views. Your unit tests can raise the same events, thereby simulating your UI very closely.

State Management: This is the topic that seems to pop up each time I read about someone's problems with the MVP pattern. The misconception is that there's no way to use Session, Cache, etc… without forcing the presentation project to have a reference to System.Web. I think that's a bit shortsighted.

Actually, the answer is rather simple. Views interact with the presentation layer via the interfaces they implement. Application state (Session) shouldn't be any different. Simply put, all we need is a state management interface that defines how to interact with any state object. Then, just like a view implements an interface, ASP.NET's Session object can be wrapped in a class that implements the state management interface.

/// This is in the presentation layer.
public interface ISessionProvider
{
    object this[string name] { get;set;}
    object this[int index] { get;set;}
} 

/// This is in the asp.net project. It's a wrapper for the HttpSessionState object
public class WebSessionProvider : ISessionProvider
{
    private HttpSessionState Session
    {
        get { return HttpContext.Current.Session; }
    } 

    public void Add( string name, object value )
    {
        Session.Add(name, value);
    } 

    public void Clear()
    {    
        Session.Clear();
    } 

    public bool Contains( string name )
    {
        return Session[name] != null;
    } 

    
    object ISessionProvider.this[string name]
    {
        get{ return Session[name];
    }
    {    
        set { Session[name] = value; }
    } 


    object ISessionProvider.this[int index]
    {        
        get{return Session[index]; }
        set{ Session[index] = value; }
    }
}

Since presenters interact with interfaces, and state has been abstracted to adhere to an interface, our presentation layer now has access to any type of state management without ever having to know the details of the state's internals… including the ASP.NET Session object (see the WinForms sample for a custom state example).

Where are We?

I said that by the end of the article we'd have the beginnings of maturing how MVP applies to .NET. Are we there yet... I don't know. I think there's still plenty of work left to be done. MVP is a relatively new approach (though MVC has been around the block many times), and the best ideas haven't been thought of yet. My hope is these ideas give you a leg up if you're looking to use the pattern and want to make it clean and usable. Better yet, what ideas do you have on how MVP can be improved upon? Take a look at the sample projects to see how the layers are truly interacting with each other. Then, more importantly, share your thoughts with your own super cool article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

TylerBrinks
Web Developer PageLabs
United States United States
Member
I'm the founder of PageLabs, a web-based performance and SEO optimization site.

Give your site a boost in performance, even take a free speed test!
 
http://www.pagelabs.com

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionWhat about authentication/access control?memberMillJe9 Jul '11 - 5:17 
Another topic that I haven't found discussed is passing on authentication information for use for downstream access control.
 
Any better options than just stuffing the authentication context into the session state?
QuestionSessionManager thread safetymemberMillJe9 Jul '11 - 5:12 
I have concerns about your implementation of SessionManager. Any static members of a class will be shared by all simultaneous http requests (i.e. all users).
 
Since we are supplying a ISessionProvider to the presenter, do we really need the SessionManager? Why not just have it be a property of the Presenter and if it is needed by anything downstream of the Presenter then the Presenter needs to pass it along.
GeneralAccessing Applicatoin State From the Unit Test ProjectmemberAdamNThompson21 Dec '09 - 3:52 
I have a question. By the way brinliant implementation of the MVP Patter over WEbForms.
 
My question is regarding accessing HttpContext from the UntiTest Project. One of the key points of this pattern is the testability. I am having an issue though I have built an interface called IStateManager as you have suggested here and it works fine when I am executing code from my view (Web Application), but If I attempt to mock the vew in a unit rest project I get a null refernence exception when I hit any code that is trying to use the state manager. I have tried adding a reference to System.Web to my Unit TEst project but it didn't help. I must be missing something here.
 
State Manager is Instantiated and used like so.
IStateManager stateManager = StateManagementProvider.GetStateManager<IStateManager>();
 
Like I said works fine when I run the application in a browser, but I cant write Unit test agenst it at all. Is there something I am missing here?
 
Thanks,
 
-Adam N. Thompson

GeneralRe: Accessing Applicatoin State From the Unit Test ProjectmemberAcoustic21 Dec '09 - 5:33 
I personally don't believe unit tests should require references to System.Web. They may sometimes, for convenience, but I don't personally like the idea. If your MVP/MVC implementation truly abstract you away from a web context, you shouldn't have to be tied to System.Web.
 
That said, here's what I would generally do:
 
- I would create a Mock version of IStateManager in your unit test using Moq, Rhino Mocks, NMock, etc...
- Allow your StateManagementProvider.GetStateManager method to use some type of IoC Container to resolve types at runtime.
- Calls to GetStateManager should then return HttpContext (or whatever HTTP-specific class you need) at runtime, and your mocked version in your tests.
 
Cheers
GeneralRe: Accessing Applicatoin State From the Unit Test ProjectmemberAdamNThompson21 Dec '09 - 10:33 
I figured since I am getting all my instances from a Provider by Interface that I am not tied to the web context. I actually have a config entry specifying that the implementation of state manager is in the View Layer (ASP.NET App). I suppose that the way I have implemented it I could use IoC to inject an implementision of StateManager to the interface that just uses a Dictionary when testing the presenter from the unit test project.
 
I am unfamilure with these (Moq, Rhino Mocks, NMock), But I think I see your point.
 
Thank you for your response.
 
-Adam N. Thompson

GeneralBillys Article not on the link specified.memberSidharthaShenoy14 Oct '09 - 19:24 
Could you let me know where to find Billys Article.
Generaldownloaded the code but errorsmemberzebula82 Oct '09 - 15:06 
I downloaded the code into my c:\downloads folder and click on the solution and get nothing but errors - none of the projects will load:
 
First Error:
------------
The application for project 'C:\Downloads\Advanced_MVP_src\MVP Sample\mvp' is not installed.
Make sure the application for the project type () is installed.
 
Second Error:
-------------
The application for project 'C:\Downloads\Advanced_MVP_src\MVP Sample\Sample.Presentation\Sample.Presentation.csproj' is not installed.
Make sure the application for the project type (.csproj) is installed.
 
Third Error:
------------
The application for project 'C:\Downloads\Advanced_MVP_src\MVP Sample\Sample.WinFormsView\Sample.WinFormsView.csproj' is not installed.
Make sure the application for the project type (.csproj) is installed.
 

I try to manually add these projects but the IDE says they are already loaded when in fact they are not loaded:
 
Here is what the IDE looks like in the Solution Explorer:
 
Solution 'mvp' (0 Projects)
-C:\..\mvp\(unavailable)
-- The Project File cannot be loaded
-Sample.Presentation(unavailable)
-- the project file cannot be loaded
-Sample.WinFormsView(unavailable)
-- the project file cannot be loaded
QuestionMVP w/ WebService (.asmx) ?memberUberNewb12 Aug '09 - 4:21 
I was just wondering if anyone had used this pattern (or any MVP implementation) with a .Net web service. I'm trying to figure out how the View would be implemented in a .asmx page.
 
Thx!
GeneralUse Attribute.GetCustomAttribute(...) instead of Type.GetCustomAttribute(...)memberigor200620 May '08 - 8:06 
protected void SelfRegister(Page page)
{
if (page != null && page is IView)
{
PresenterTypeAttribute attr = Attribute.GetCustomAttribute(page.GetType(), typeof(PresenterTypeAttribute)) as PresenterTypeAttribute;
 
if (attr != null )
{
PresentationManager.RegisterView(attr.PresenterType, page as IView, _state);
}
}
}
GeneralFix formattingmemberVictor Boba9 Oct '07 - 4:51 
Very hard to ready article because the horizontal scrollbar is enabled due to the formatting. Please fix overflow.
GeneralService Layer (DAO)memberdasratso15 Sep '07 - 18:03 
Loved the article and modified my existing MVP code using your ideas as I was also frustrated with some of those common problems. One issue that keeps coming up for me is that the view has to pass the Data Service object to the presenter. Is your solution to simply add a Service object to the presenter as a property? Why does the pattern want the Service passed from the view anyway? I'd LOVE to see your sample code have a Data Service project included. Thanks again for the great post.
 
b u n g a l a y
QuestionRe: Service Layer (DAO)memberdasratso16 Sep '07 - 14:24 
Followup: I realize that the presenter needs to be independent from the service and that's why a IDAOService interface implementation is passed from the view. I just would like to know where you pass this DAO still keeping it independent. THANKS! -Chad
 
b u n g a l a y
AnswerRe: Service Layer (DAO)memberAcoustic17 Sep '07 - 5:39 
I'm a little confused about what you're asking. My project doesn't have an IDAOService interface. If it did, I wouldn't be passing it from the view. The view shouldn't even know about a service layer. Were you looking at some other code?
 
Notion ONE - Excellence through Service.

QuestionRe: Service Layer (DAO)memberdasratso18 Sep '07 - 4:58 
Sorry for the confusion. I was referring to that part in your article:
 
"One area I may disagree with Bill is that views should also not know what data layer type (or DAO interface type) to pass to a presenter. I'm of the opinion that the view's shouldn't have a reference to any data layer (i.e. anything upstream of the presenters)."
 
Bill uses the typical pattern where you pass the DAO Interface type from the view to presenter in the constructor. I just wanted to know what your ideas were on how the presentation gets, and uses the DAO service. I agree that the view shouldn't reference the data layer, but I want the presenter to only know the DAO Interface type, and not have to reference my implementation.
 
Hope that made a little more sense.
 
Chad
 
b u n g a l a y
AnswerRe: Service Layer (DAO)memberPaul Hatcher24 Oct '07 - 7:28 
Don't believe that it's the view that's passing the DAO, but the overall controller, i.e. the page. A fragment of code from one of my current projects...
 
protected override void InitializePresenters()
{
IContactDao dao = DaoFactory.ContactDao();
ContactEditPresenter presenter = new ContactEditPresenter(ContactEditView, dao);
ContactEditView.AttachPresenter(presenter);
 
Presenter = presenter;
}

 
Don't see an easy way around at least one part of the project knowing how to construct the presenter. The only other approach is some form of IoC container like Winsor etc, and I generally prefer to have code as code not XML unless there's a good reason why.
 
Paul

GeneralInteresting ideamemberCristian Odea7 Sep '07 - 4:28 
Interesting solution for this problem that was bothering me for a while.
 
I like the clean separation between the layers, however, I'd like to see this in action in a difficult context, where the presenter would have a more complex interaction with the view.
 
Good article, thank you for sharing it.
GeneralRe: Interesting ideamemberAcoustic7 Sep '07 - 4:47 
Thanks! I've been using this patter with a current client by request. As it turns out, their business logic can be rather difficult, especially when deciding which logic goes on the server (a WCF solution), and which logic stays on the client (the presenters). Thus far the architecture has worked extremely well. I'd post some complex code samples if it wouldn't violate the contract.
 
I can't ask you to take my word for it, but I've found the pattern works well, even for difficult scenarios.
 
Notion ONE - Excellence through Service.

Generalmult-itier architecture in asp.netmemberarturbl5 Sep '07 - 5:59 
Hello,
 
You may take a look at http://www.codeproject.com/cs/design/WebFormsASPdotNET.asp
article which presents the alternative to MVC/MVP approach and also addresses your
concerns about MVP. Any comments will be appreciated.
GeneralRe: mult-itier architecture in asp.netmemberAcoustic5 Sep '07 - 6:40 
Thanks for pointing me to this article. The author has taken a very "Ruby-esque" approach to his page life cycle. If you're not already familiar with how Ruby on Rails works, I'd recommend you check out http://rubyonrails.org/[^]. In short, Rails takes a "convention over configuration" approach. Specifically, Rails use a true MVC pattern that's driven by the request path and query string. In Rails, all incoming requests are handled by a controller. That is to say, the controller is the point of entry for any given request. The view, in this case, is used purely for display.
 
The question is how does this compare to ASP.NET. By default (that is, without writing HTTP handlers or modules), the code behind an ASP.NET file is the entry point for incoming requests. This convention makes it difficult to implement a true MVC pattern since the view is taking requests, not the controller.
 
The article you referenced attempts to put the controller at the forefront of the request cycle. It's an interesting approach, but I'm not sure that it provides a tangible advantage to the standard .NET page request life cycle. The MVP pattern really provides a layer of abstraction from the UI that's highly testable.
 
The main difference here is that the code used in the MVP layer can be easily reused in an WinForms project, Console app, Windows Service, or any other type of "view" you can think of, thanks to the use of simple interfaces. The article you referenced is heavily coupled to the ASP.NET pipeline, and wouldn't work at all outside that context. In other words, MVP strives for reuse while the other article strives to mimic a Rails convention.
 
Interesting read, though. Thanks!
 

 
Notion ONE - Excellence through Service.

GeneralRe: mult-itier architecture in asp.netmemberarturbl5 Sep '07 - 6:57 
Hello,
 
Im really sorry that you read only the first few lines. I pointed you to my own article. My article was inspired by Ruby on Rails framework only in the sense
that multi-tier architecture is posssible. Anything else is my own ideas without
copying or mimicing Rails. I decoupled three tiers
by using interfaces. Please read more than only few lines
before you write such a judgement.
Firstly, If you read more you have noticed that there is a http handler used which
takes care of url rewriting, creating and calling controller/presenter methods.
Secondly, everything that you wrote about my article is flat wrong because you people
want to read only headline and pass a judgement. Effort first then judgment.
Thirdly, http module is an entry point not controller/presenter
Fourthly,the whole appoach is an interface based.
PLEASE PLEASE read, make an effort
 
arturbl
GeneralRe: mult-itier architecture in asp.netmemberAcoustic5 Sep '07 - 8:05 
I read you're whole article, top to bottom. My points still stand, and, for the record, were not critical at all. There are no judgements, just simple observations. My point is that you use a controller-first architecture like Rails.
 
Frankly, you need to calm down a bit - you asked me to read the article and give observations. I did, and I stand by based on the current content of the article. Further, my points on how your architecture isn't portable to a non-asp platform still stands in terms of a HTTP handler being the controller broker. It's not being critical, it's just a fact.
 
Seriously, don't ask for opinions if you don't want to take them.
 
Notion ONE - Excellence through Service.

GeneralRe: mult-itier architecture in asp.net [modified]memberarturbl5 Sep '07 - 8:25 
Thank you for reading the whole article and your remarks. I must say that you are very quick.
If you incorporate url mapping/rewriting in your http module then at some point you need to call some methods. In my case methods of the controller/presenter are called
on run-time based on a given url content. I do not know how you would have url mapping without calling controller/presenter methods. Clearly you need something between http module and aspx page.
The whole idea of using interfaces where controller talks to model, view and controller talk to each other is because of portability.
Take out http module out and try to write win forms app and you will see that my approach is fully portable. Controller knows almost nothing about view and talks to model through interface methods. None of the three tiers has any knowledge about http module. Controller is not as powerful as in Rails. Its methods are called by view through interface methods. If you write console or win forms app you should not modify the structure of model or controller. Just get rid of http module and aspx page. I hope that clarifies things.
Yes, in case of win forms app or console one you need controller-breaker. You simply
intstantiate controllers class somewhere in a code. But by no means you change model or controller structure. When you switch between web/win forms/console apps you may add or remove some code but never in controller or model (you remove controllers properties in case of none-asp app,but you never change constrolers structure). This is what I mean by portability
I stand by the fact that my approach is as portable to non-asp environment as interface based approach is.
 

 

 

 
-- modified at 16:01 Wednesday 5th September, 2007
GeneralRe: mult-itier architecture in asp.netmemberAcoustic5 Sep '07 - 14:28 
I'm still not clear... your controllers are loaded by the HTTP module. If you take out the module and move to a WinForms or Console app, what's going to load the controller? My point is that you have a convention, the module, to do that work. That module depends fully on ASP.NET. Obviously, you're not going to have an HTTP module in a WinForms app. To that end, there is still a dependency, despite the abstraction further down the pipeline.
 
You stated, "Yes, in case of win forms app or console one you need controller-breaker. You simply intstantiate controllers class somewhere in a code.But by no means you change model or controller structure."
 
What you're saying is that you have to write new code to do what your HTTP module does if you change UI paradigms. The MVP pattern in Bill's and my articles don't require that infrastructure. They're 100% technology agnostic, and, short of creating new views (wich all of our projects would require), there's no changes necessary, and no additional code.
 
My point is that you have a really cool concept, but it's simply not comparing apples to apples when you compare your idea or Rails to this type of MVP implementation.
 
Great ideas, though. I still enjoyed your article.
 
Notion ONE - Excellence through Service.

QuestionWhat about type savety?member= M =3 Sep '07 - 2:51 
Doesn't mapping views to presenters lose type savety?
I like the idea of having less code,
but I rather have my code checked compile time then run-time.
In your example it's possible to map any presenter to any other view
and only find out at run-time that the mapping is wrong.
Any ideas on making it type save?
AnswerRe: What about type savety?memberAcoustic3 Sep '07 - 9:54 
Check out the latest source code. I've updated it to get rid of the type mapper all together (though I just noticed the article's text is still out of date.
 
Right now the mapping is attribute-based, which helps provide some abstraction, but no real type safety. I does, however, guarantee the type of presenter that will act on the view. I'm in the process of constructing a more elegant solution using generics so the types can be checked at compile time.
 
Notion ONE - Excellence through Service.

GeneralRe: What about type savety?member= M =5 Sep '07 - 5:19 
If it can be done, generics seems like the way to go.
But it just feels like a fundamental problem.

GeneralRe: What about type savety?memberAcoustic5 Sep '07 - 8:11 
I agree. I haven't found a good solution yet other than the attributes on the views (see the latest source code).
 
Notion ONE - Excellence through Service.

Generalthanksmemberszepiet11 Jul '07 - 12:45 
Part of my master thesis is about MVP, I came across Your article and I have to say that it will helps me a lot and also that If you figure it out yourself, You are genius,
thank You very much again
 
regards
Krzysztof Szepietowski
GeneralRe: thanksmemberAcoustic15 Jul '07 - 12:22 
I'm flattered that my article will help with your thesis. In case you're interested, I've refactored the project a bit to further decouple the views in favor of using events. I'll post the updated code and this thread when I get the source updatd. Hope it helps!
 
Notion ONE - Excellence through Service.

QuestionWhat about ICacheProvider?membermrjmwcom16 Oct '06 - 7:52 
I know we can do the same thing with System.Web.Caching.Cache but is there a better way to do it with Cache so this wouldn't be necessary? Or would this be the best type of approach for Cache as well?
Thanks!
JMW
AnswerRe: What about ICacheProvider?memberAcoustic5 Dec '06 - 17:34 
You can do it however you need, using an approach like the session state in the demo gives you freedom for multiple types UI platforms. You wouldn't want to use ASP.NET's session state for a WinForms app. You also wouldn't want to use ASP's caching in a WinForms context. I'd stick with some type of provider model or interface so the underlying implementation can be abstracted.
 
Notion ONE - Excellence through Service.

QuestionSessionManager?membermrjmwcom16 Oct '06 - 5:42 
Looking at your example I found the SessionManager...
 
    /// SessionManager stores an instance if an ISessionProvider for state management.  This
    /// allows the Presentation project to avoid references to System.Web.  Consumers implement
    /// ISessionProvider based on how state is managed.  In the case of ASP.NET, the 
    /// implementation would wrap the System.Web.SessionState.HttpSessionState object
 
But still don't understand why the SessionManager is neccessary. With ISessionProvider alone you would not need to reference System.Web in the presentation project, would you?
AnswerRe: SessionManager?memberAcoustic16 Oct '06 - 7:50 
The original idea for the SessionManager was to help with making multiple calls to more than one presenter at the same time. I had originally started with a Singleton pattern so all instances of presenter implementations could share the same session object. The sample code hasn't built that idea out as much as it has put a good place holder for the sake of ease.
 
Notion ONE - Excellence through Service.

GeneralAbout .Execute...memberAcoustic16 Aug '06 - 3:36 
Since the original posting of this article I've stopped using the "Execute" paradigm all together. Every last line of code related to it was deleted from my own personal project, so for those of you who continue to have great suggestions, no need to dwell on the old stuff.
 
What new ideas does everyone have?
 
Notion ONE - Excellence through Service.

GeneralRe: About .Execute...memberMrFixxiT[Leones]18 Aug '06 - 12:44 
Maybe you could edit the article itself by replacing the Execute parts with what you use right now! Cool | :cool:
 
And of course a thanks for your contribution and the time to respond and change your opinion.
GeneralRe: About .Execute...memberAcoustic18 Aug '06 - 13:05 
I absolutely will update the article when I have the sample prject in a state that's worth re-posting. I'm also happy to take more ideas/snippets/etc... into account before I edit the article, so post away!
 
Notion ONE - Excellence through Service.

QuestionDelegates instead of Execute?memberSam At Work15 Aug '06 - 11:23 
I'm rather new at .Net so I may be overlooking something obvious.
 
Couldn't the view interface define delegates for every one of the events it needs to respond to?
 
The view implementation would have calls to the delegates in the various events it needs the presenter to respond to.
 
When the presenter inits the view, it assigns its own member methods to the views' delegates.
 
When the presenter gets a call to one of the methods it assigned as delegates, it turns around and asks the view for the data it needs and does whatever processing it needs to do.
 
I hope I'm explaining this correctly. (And that I'm not embarassing myself too badly. Smile | :) )
 
I'd be thankful for any insight you could provide me since I'm thinking of using this for a rather large project.
 
Thanks.
AnswerRe: Delegates instead of Execute?memberAcoustic16 Aug '06 - 3:33 
Thanks for the suggestion! You're right; an event structure could easily be defined in the interfaces and used to invoke the presenters. It may simply be easier to call a method exposed by a presenter so parameter passing is easier, but what you outlined is well within the realm of possibility.
 
Notion ONE - Excellence through Service.

GeneralRe: Delegates instead of Execute?memberSam At Work16 Aug '06 - 4:14 
Thanks for the validation! It really helped improve my confidence in my current design. Cool | :cool:
 
Thank you for the great article (just realized I hadn't mentionned that before).
GeneralUse Events Instead of Executememberjimmyseow1232 Aug '06 - 4:25 
Using the abstract execute method seems cumbersome and unwieldy.
May I suggest the use of Events instead?
For example, you could define the Login event in your view interface.
Then, in your loginButton_Click subroutine, just raiseevent Login.
In your presenter class, use
Public Sub Login() Handles view.Login
dim userName as string = view.UserName
dim password as string = view.Password
...
end sub

GeneralRe: Use Events Instead of ExecutememberAcoustic2 Aug '06 - 8:44 
True, you could use events to respond to the UI, but that raises a number of problems with MVP theory. First off, when the presenter responds to the UI’s events you rapidly approach an MVC pattern. Next is the issue of references. Take a datagrid’s ItemDataBound event for example. In order for the presenter to subscribe to that event, the presenter would be forced to have a reference to System.Web, something you absolutely should not do to follow the MVP pattern.
Another problem with this approach is that you’ve more tightly coupled the presenter to a particular type of view. As I’m sure you know, the delegate signatures for many controls do not mesh between ASP and WinForms (or other sources). You’d be forced to write an entire set of classes so any type of view could pass the same, consistent, expected data types to the presenter. That brings us right back to square one – the views are now engaged in non-view logic.
 
I totally agree about calling the Execute method; since writing this article I’ve come to dislike every aspect of that idea. A good point was made in a previous post regarding how the self-documenting nature of the presentation layer is lost using a generic Execute method. I still haven’t found a good answer to the problem of coupling and abstraction between the layers. Like I said, I like the idea of events, but there are too many immediate limitations to fit that into this MVP sample. Until I find a good alternative, I’m resigned to the fact that the true advantage of MVP is that it’s like partial classes across assemblies to aide in testability.
 
Notion ONE - Excellence through Service.

GeneralRe: Use Events Instead of Executememberjimmyseow1234 Aug '06 - 21:34 
I may not have been clear in presenting my ideas.
To subscribe to an ItemDataBound, don't let the presenter subscribe to it directly.
Let the View subscribe to it, then let the View expose a different event.
For example,
 
In the usercontrol code-behind,
Public Event ItemSelected(ByVal PositionLabelIndex As Integer) '==> expose this event to the presenter
Private Sub gvBomNarrations_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles gvBomNarrations.SelectedIndexChanged
RaiseEvent ItemSelected(CInt(gvBomNarrations.SelectedValue))
End Sub
 
In the View,
Public Interface IViewBomNarrations
Event ItemSelected(byval value as integer)
End Interface
 
In the presenter,
Public Class BomNarrationsPresenter
Private WithEvents _view As IViewBomNarrations
Private Sub _view_ItemSelected(byval value as integer) Handles _view.ItemSelected
...
End Sub
ENd Class
GeneralRe: Use Events Instead of ExecutememberAcoustic7 Aug '06 - 17:54 
I understand your point, but what I'm saying is that your example describes how MVC (Model-View-Controller) works. All you've done is take the ASP.NET event structure and have the view dumb it down for the presenter's sake. Now your view has to be smart enough to know how to translate UI data types into .NET primitives, and potentially even business objects, expected by the presenters. Further, your example forces the view to know the correct order in which events should be fired (remember, views are not always ASP.NET pages) to keep the presenter's workflow correct. One of the major ideas for MVP is for the view to be as simple as possible. The presenter should simply use properties and methods to retrieve the data it needs rather than trying to respond to events that will likely be inconsistent between various views. Events can be used, where appropriate, but not by adding complexity to the views.
 
Good ideas, though. Thanks!

 
Notion ONE - Excellence through Service.

GeneralRe: Use Events Instead of Execute [modified]memberMrFixxiT[Leones]18 Aug '06 - 12:36 
I guess what I wrote here is what Sam At Work suggested too, but I hadn't read his posts and your (Accoustic's) reaction yet...Roll eyes | :rolleyes:
 
You could use events like suggested, but don't send any UI-mapped-to-.NET-primitives values as parameters, but instead let the presenter get the values it thinks it needs itself.
 
But that's pretty much like calling a method on the presenter. The only difference is that the presenter can choose to subscribe to the even or not. In the method implementation the presenter must have implemented the method to let it be called.
 
But now that I think of it, we still have only one presenter implementation for the view, so the option of letting the presenter choose whether to subscribe is a bit weird.
 
I hope I'm being clear and I hope I'm making sense as it's quite late. Wink | ;) O, and of course because this is my first post! :P
 

-- modified at 18:39 Friday 18th August, 2006
GeneralRe: Use Events Instead of Executememberkichasrini26 Nov '06 - 9:11 
I just happened to read thru the whole MVP discussion chain, though a lot late, I thought I would share my view as well. Having events as a way of communicaton between the view and the presenter, does give us the flexibility of making the View totally unaware of the Presenter. My question is why should the View know about the Presenter? The following code would allow us to test the code easily with any ILoginView implementation.
 
public LoginPresenter(IView view,Model model)
{
((ILoginView)view).OnValidateUser += this.ValidateUser;
}
GeneralRe: Use Events Instead of ExecutememberGlyn Darkin18 Jun '07 - 4:05 
How about using "convention" to match the CommandName of an event, e.g. button click, to the action taht you want to call on the present. That way you can use reflection to call the action without having to have a generic execute method, e.g.
 

protected void loginButton_Click( object sender, EventArgs e )
{
Type presenterType = base._presenter.GetType();
BindingFlags flags = BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance;
MethodInfo action = presenterType.GetMethod(((Button)sender).CommandName, flags);
action.Invoke(target,null);
}

Obviously you can refactor the reflection code out into a helper, it is just here for illustration.
 
Therefore you can have a CommandName = "Login" on the submit button and a public void Login() on the presenter.
 
Great article by the way
GeneralWebsessionprovidermemberkaspyanand18 Jul '06 - 22:46 
What is the use of methods add,contains and clear in websession provider? how can I access them,since presenter is only using ISessionProvider to put session values..
thks
GeneralRe: WebsessionprovidermemberAcoustic19 Jul '06 - 2:10 
I don't understand your question. Can you be more clear?
 
Notion ONE - Excellence through Service.
GeneralRe: WebsessionprovidermemberAcoustic19 Jul '06 - 8:12 
I re-read your post, and I think I understand your question. The point is that I intended to implement the interface to support those methods, and left it as generic as possible for this article. I started by creating a functional wrapper for ASP's session object, and didn't implement the interface until later. I wouldn't do that for a real application, but in the case of this sample I took a backwards approach. You're right, the presenters can't take advantage of methods not exposed by the interface, and as such they're not useful outside of ASP.NET.
 
Notion ONE - Excellence through Service.
GeneralRe: Websessionprovidermemberkaspyanand20 Jul '06 - 7:43 
i am doing a real project..and have used your idea of session management..thks..brilliant idea..

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 6 Sep 2007
Article Copyright 2006 by TylerBrinks
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid