• [转帖]ASP.NET下的MVC与MVP


    This article is targeted as support for Catharsis framework knowledge base. It describes the MVC design pattern, compares it with MVP in the ASP.NET world.

    Sources

    The Catharsis framework articles: http://www.codeproject.com/KB/applications/Catharsis.aspx

    The Catharsis source code: http://www.codeplex.com/Catharsis

    Catharsis web frameworkis completely based on MVC. If you would like to examine the Windows solution based on WPF - there is a small but completely working Example gathering best-practices: Download WpfMvc.zip - 35.65 KB (opposite to this ligthweight example is the multi-tier WPF application included in Catharsis)

    Catharsis-title.png

    MVC, MVP, ASP.NET

    These days bring the radical change into the ASP.NET development. After years of handling .aspx pages with their robust events (Init, Load …) we are facing new technology: ASP.NET MVC. This could be revolutionary tool which could strengthen position of ASP.NET as the web platform. Hand in hand it also means that newcomers will be looking for overviews which can help them to jump in. This article should simply explain the MVC design pattern mainly for .NET developers coming from previous ASP.NET versions (preceding ASP.NET MVC). In contrast I've appended Windows client example based on WPF –> The reason? (well firstly I needed that - as a proof of concept, that after all 'improvements' WPF can be adjusted to MVC; secondly) You can run it without any other stuff. VS 2008 and .NET 3.5 SP1 is enough.

    MVC design pattern in comparison with MVP on ASP.NET platform

    ASP.NET MVC among others, has two main pillars:
    1) Routing – which handles all requests as the direct calls to the controllers’ actions (http://MyServer/Person.mvc/List/ does not navigate to default file in the directory Person.mvc/List/ - but is transferred to call of the Action “List” on the controller “Person”) and
    2) Views and pages almost do not have life-cycle events, because there is no need for them – everything was already handled by controller, very very before the View even came into play.

    The more I had observed the web to see how others are accepting this new techniques and including them in their solution, the more I realized that the MVC design pattern is not as well known as it should be. For example there are some discussions about direct support for JQuery in APS.NET MVC, instead of any other approach. Well this requirement comes from not so familiar knowledge of the ASP.NET MVC and MVC design pattern as well. At the end of this article - I do believe - you will understand me.

    Before we start digging into, let’s make some history overview and also very important comparison with MVP.

    Web-Forms, .aspx Pages

    Web-Forms (.aspx pages with just one FORM tag on the page with runat=’server’ attribute) where introduced in the very beginning of the .NET (1.0). This concept came in the times of VB script .asp pages (if talking only about MS world). Web-Forms were presented as the totally different approach with page handlers, which were firing dozens of events (PreInit, Init, PreLoad, Load…). These events were suggested as the right place for calls to business logic (Business rules, Data access etc.). Why? Because these events were the center point of your application. 

    In contrast with VB script (.asp pages) this architecture was tremendous change. It was jump from in-line html wraped in VB Script into real OOP world provided by .NET C# (still top product). OK, it sounds really good.
    But surprisingly: everyone (developer) sooner or later started to tweak this functionality, something was not correct. Viewstate started to be deadweight, as well as the over any limit growing Sessions. Life-cycle event-set was soon revealed as ‘easy-to-remember’ as the names of all US states. But there were these features (and many others) and it was confusing to use them accurately.  

    The .NET evolved and the .NET 4.0 is almost knocking on the door. But Web-Forms are almost the same. To use Web-Forms as they are is not so easy on larger projects. Therefore many communities were established with one purpose - provide some extensions which could make ASP.NET development easier. Microsoft decided to support community injecting the MVP design pattern into the .aspx world, and started to call it best practices.

    Web-Forms improvements based on MVP, WCSF

    Some of open source communities, which started improving the Web-Forms, did bet on the MVP design pattern. Good and working example is WCSF. In some sources you can find typical idea: MVP has evolved from the MVC. But what is really MVP and how differs from MVC? Well, let's spend some time and describe the Model View Presenter in more details.

    Vocabulary for MVP and MVC

    Sometimes you can hear: MVP is similar to MVC.
    Then I have to say, yes, but as similar as is the C# similar to Java. You can read Java code very quickly. But if you’ll be sit to the PC with ‘Eclipse’ instead of Visual Studio, how long will take you to produce ‘Hello World’ application?

    First of all we need to correctly ‘localize’ the words in both abbreviations. Look at this two triplets:
    Model View Controller
    Model View Presenter

    For this article we will prefer MVC syntax and adjust MVP.

    The first homophone word is Model.

    MVC: Model == Plain container for storing references. Model has properties (ValueType, Objects even Collections) but does NOT have methods. This is great advantage of the Model, because whatever information you will need on View, put it in the Model - May be not so obvious but that's so wonderful place for AOP extending...

    MVP: Model == Business. Model is not model as in MVC. It in fact represents the Business Facades or Services (or whatever you named it) which allows you to access objects (Entities, DataTables). This Model-Business mainly contains methods! Add(), Remove(), Update() ….

    The second homophone word is View. 

    MVC: View == View represents UI (user interface). View takes care for nice layout, smart controls, images, hyper-links. All that stuff is built from information stored in the Model. View exposes Controller's Actions via 'buttons' and 'links'. When they are clicked – ASP.NET MVC directly creates Controller and calls its Action – and the View itself is lost in the past.

    MVP: View == Exposes properties to its Presenter, and as Presenter executes all needed calls to the Model-Business, assembles itself (View) by filling its exposed properties. The user’s requests are handled by Views methods. In these methods the Presenter is asked to communicate with Business and refill Exposed properties.

    The third words are finally different not only by meaning but even by name

    MVC: Controller == User requests are primarily routed to the Controller’s Actions. View at this moment only gathers the user inputs, which are transferred into Model. Controller then calls Business to ‘Get’, ‘Update’, ‘Delete’ etc. and refills the Model. Next the View renders the Model’s content.

    MVC: Presenter == View creates and asks presenter to get or set data from Model-Business. After Presenter fills all exposed View’s properties, the execution continues on View side.

    MVP Schema

    Now if we know the real meaning of the abbr. words, we can look at the MVP example:
    mvp3.png
    The picture starts with user’s request. In the world of Web-Forms (WCSF) this event (I.) is handled by some of the life-cycle events on the view == page. Then the presenter is created and asked to get or set data (II.) from the Business (Model). Finally the Presenter fills the View’s exposed properties (III.) and the rendered view is as a response send to the user.

    This approach was introduced also to improve test driven developmnet. The separation of concern (which is the crucial point of a good design) could be realized with the IView interface. This is what the Presenter knows and acts with. Presenter is responsible for exactly defined piece of work (discribed by the properties of IView) and can be easily reused. And also mock IView objects can be used to play the View role in unit tests.
    Due to MVP the ASP.NET applications could be finally really well designed and multi-tier. There could be business tier (Model-Business), Pages with nice user interface without data dependency, and the workhorse (Presenters) which transfers data between those two.
    And what’s more, that all is running with the Web-Forms as it is.

    Implementation

    Objects could (should) be created by some 'factories' using DI (Dependency injection == Inversion of Control IoC (Catharsis - part XIV. - Dependency injection (DI, IoC) ). The MVP design pattern will of course work without these techniques, but DI not only allows good testing but at first it force you to think about View and Presenter as the two independent objects.

    Collapse

    public interface IView { IList<string> Links { get; set; } }
    public interface IPresenter 
    { 
        IView View { get; set; }  // for pure DI (IoC) is set; enough
        void CreateLinks(); 
    }
    

    Collapse

    public class View : IView
    {
        // IView implementation
        public IList<string> Links { get; set; }
      
        // Presenter could be created by this View in constructor
        // or provided by IoC factory
        public IPresenter Presenter { protected get; set; } // public setter is enough;
    
        public View()   // instead of using IoC factory
        {               // let's create Presenter in View's constructor
            Presenter = new Presenter() { View = this };  // in this example ...
        }
    
        public void OnLoad()   // This method is called by ASP.NET
        {                      // as reaction on user's request
            Presenter.CreateLinks(); // View calls its Presenter    
        }
    } 
    

    Collapse

    public class Presenter : IPresenter
    {
        // the center point for Presenter work is it's View
        public IView View { get; set; }
    
        // there could (should) be the Business call instead...
        public void CreateLinks()      // ...of the dummy example
        {
            View.Links = new List<string>() 
            {
                "http://www.codeproject.com/KB/applications/Catharsis.aspx"
              , "http://www.codeplex.com/Catharsis" 
            };
        }
    }
    

    So simple and wonderful the MVP design pattern is.

    MVC for ASP.NET

    After five years (or more) of promoting Web-Forms, Microsoft decided to establish (almost independent) team of Guru’s with only one aim: Break its treasury – Web-Forms. They (ASP.NET MVC team) in fact created very trivial (really very simple) http handlers which introduced MVC design pattern into ASP.NET.

    How it works? Well, the ASP.NET page handler is removed. Instead there is the smart url routing hanlder, which transforms the user requests to Controller Action calls. That’s all.

    Really, that’s all. There are some brilliants in the ASP.NET MVC implementation of course: among others the built-in AOP framework; very useful FORM-to-Model binding; etc. By the way, if you (or I) were smart enough (as these mentioned Gurus), we could do it ourselves years ago – just by using the ability of ASP.NET to change or extend the http handlers.

    MVC Schema

    Well how the MVC Design pattern works:
    mvc3.png

    The user’s request is send to the server, where is handled by URL-Routing handler. If user asks for http://MyServer/Person.mvc/List/ the handler translates it as: create Controller named Person and invoke its action “List”. So the starting point is the Controller at this design pattern.

    (AOP – the ASP.NET MVC allows simply to append AOP filters before Action invocation and after Action execution. It enforces the separation of concern. Tremendous)

    Controller’s Action then Sets or Gets data into persistence (I.) using Business (facades, services). The results (Collection, Items, CodeLists, NavigationLinks) are stored in the Model (II.). When Model is filled the View is asked to render the user output using the information stored in the Model (III.). View (page or control) communicates only with the Model.
    One of the (at first sought not so clear) advantages of that approach is the AJAX support. If your application at some point need the combo-box (drop-down list) to be added into page, you can asynchronously call the Controller to fill Model with Items (options) and pass them to the UserControl which renders <select><option> …</select>. That small piece of xml could be easily sent to client browser and appended into the display tree.

    Collapse

    public interface IModel { IList<strings> Links { get; set; } }
    public class Model : IModel
    {
        public IList<strings> Links { get; set; }
    }   

    Collapse

    public class LinkController    // Link Prefix is used to demonstrate URL routing
    {
        protected IModel Model { get; set; } // e.g. this could be injected by IoC 
        protected IView  View  { get; set; } // or in constructor ... 
    
        // link on page should look 
        // http://MyServer/Link/ShowLinks  -- this is the source for URL routing 
        public virtual void ShowLinks() // the ENTER POINT
        {                               // ASP.NET MVC directly calls this method(Action)
            Model = new Model();        // instead of calling View.aspx !!!
            Model.Links = new List<string>() 
            {
                "http://www.codeproject.com/KB/applications/Catharsis.aspx"
              , "http://www.codeplex.com/Catharsis" 
            }; 
            
            View = new View();
            View.Show(Model);  
        }
    }
    

    Collapse

    public interface IView { void Show(IModel); }
    public class View : IView
    {
        // Model is container for data, directly supplied by Controller
        public IModel Model { get; set; }
    
        Show(IModel model) // this could be the .aspx page, but in contrast with MVP  
        {                  // View is created and firstly called by controller - not ASP.NET
            Model = model;
            // TODO fill html with elements according to the Model data ...
        }
    }
    

    What it brings? The cleanness and performance. No page.aspx was called! No events (Init, Load) were raised. No user Http handler was needed. Only your one simple Action was directly called (via URL routing) and the xml provided by UserControl was retrieved. Sorry but this is miracle. Do you need anything like JQuery? Why? (Well, I only tried to demonstrate the power of that great ASP.NET MVC solution – you can still use JQuery like stuff if you like it!)

    Summary

    If you would like the see who MVC works in practice, examine Catharsis Examples. They should run when DB scripts are installed, and you can observe how simple is to use this design pattern in life. (Try to select role in Web example – after button click the AJAX will download the combo-box and paste it into the page – the complete MVC cycle was ran behind)

    There is an (my) intention to provide you with MVC solution based on WPF. The simple example is created and if you take some time to observe, you will see ... MVC design pattern encapsulated in best-practices techniques, fully working, using WPF. If there will be some time, I would like to append also some description...

    Enjoy MVC

    Sources 

    The WPF simple Example of MVC gathering best-practices:Download WpfMvc.zip - 35.65 KB

    The Catharsis framework articles: http://www.codeproject.com/KB/applications/Catharsis.aspx

    The Catharsis source code: http://www.codeplex.com/Catharsis

    Enjoy MVC with Catharsis

    History 

    PS:

    In one note below this aritcle, there was one really interesting question:  

    How to convert old MVP application into MVC, when there is lot of UserControls which have its own Presenters?

    I am sure that the answer shouldn't be in lost somewhere in the discussion! I do understand it 100%. I thought and probably went the same way! Finally, I've got solution, is pure, simple and nice. And I really wonder for your reaction.
    1) Let's say we want to share 'user control' with Navigation links. There will be only the list of anchors tags (<a>) rendered by this 'user control':

    Collapse

    ... 
    <a href="Person.mvc/>Person</p>
    <a href="Address.mvc/>Address</p>
    ...
    

    2) That stuff could be stored in the Model of that type:

    Collapse

    public interface IModel { IList<string> Links { get; set; } }

    3) Well, it could be provided by Navi.ascx control, which is derived from smart base:

    Collapse

    public class Navi:  ViewUserControl<INaviModel> { ... }

    (...we are still talking only about simple basic ASP.NET MVC implementation ... nothing special ...)
    4) Now we should assure, that every View (page) which will use the Navi.ascx will use Model which also implements INaviModel (that's the OOP)
    5) Finally We should create [NaviFilterAttribute]
    with which we will decorate every Controller or Action which should end with View using Navi.ascx
    6) in NaviFilterAttribute just do this:

    Collapse

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
       var model = ((IControllerWithModel)filterContext.Controller).Model as INaviModel;
       if (model != null)
       {
           model.Links = new List<string>() { "Person", "Address"};
       }
    } 

    7) That's it! Cool! You will like it! :)
    8) And solution is pure AOP (aspect oriented programming) :)
    I would suggest to you to observe Catharsis web example - among others, there is Navi like control with described behavior
    Enjoy MVC with Catharsis
    Radim Köhler

    License

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

    这是转帖,原文来自 http://www.codeproject.com/KB/aspnet/AspNetMvcMvp.aspx

  • 相关阅读:
    [设计模式]门面模式
    [设计模式]装饰者模式
    IE8半透明不显示出文字
    解决IE6,IE7不能隐藏绝对定位溢出的内容
    [设计模式]适配器模式
    linux学习网站
    PPP协议解析
    c语言面试题__指针篇
    单链表反转
    16道C语言面试题
  • 原文地址:https://www.cnblogs.com/68681395/p/2056090.html
Copyright © 2020-2023  润新知