Programming Microsoft ASP.NET 4 - Dino Esposito [321]
public interface IDefaultView
{
IList String Message { get; set; } String Symbols { get; set; } } You need to be able to read and write the content of the text box that contains the list of current symbols. Additionally, you need to read and write the content of a message, such as an error message or the time of the last update. You also need a collection of objects representing the stock information you want to display. With the view contract defined in detail (for example, agreement is required on IDs), designers and developers can start working in parallel. The nicest thing is that it really works like this in practice—it’s not a theory or an empty platitude trying to sell a certain point of view. Implementing the Interface public partial class Default : Page, IDefaultView { ... } The main responsibility of the view is hiding the details of the user interface elements. The interface exposes just a string property representing the stock symbols to retrieve, but the use-case suggests the user is expected to type names in an input field. Subsequently, the implementation of the Symbols property wraps the text box, as shown here: public partial class Default : Page, IDefaultView { ... #region IDefaultView Members public IList { get { return GridView1.DataSource as IList set { GridView1.DataSource = value; GridView1.DataBind(); } } public string Message { get { return lblMessage.Text; } set { lblMessage.Text = value; } } public string Symbols { get { return txtSymbols.Text; } set { txtSymbols.Text = value; } } #endregion } Where does StockInfo come from? That could either be one of the entities that populate the business layer or a specific data transfer object that is returned by the service layer. (See Chapter 14.) In this case, for simplicity, you can assume that you share the domain model with the presentation layer; so StockInfo comes from an Entities assembly referenced by both the service layer and the presentation. public class StockInfo { public String Company { get; set; } public String CurrentQuote { get; set; } public String Change { get; set; } public String Date { get; set; } public String Time { get; set; } } The next step is adding a presenter component to the view. The presenter is a plain .NET class that must be instructed to work against any objects that implement the view interface. Creating the Presenter Getting a Presenter’s Instance public partial class Default : Page, IDefaultView { private DefaultPresenter _presenter = null; protected void Page_Load(Object sender, EventArgs e) { _presenter = new DefaultPresenter(this); } // Implementation of the IDefaultView interface ... } An issue you might face is arranging a convenient naming convention to give each presenter class a name that is both unique and meaningful. The name of the page with a trailing string such as Presenter is a good approach; anyway, feel free to adapt it to your needs. Using the Presenter The presenter is expected to expose a method for each possible action invoked by the user. Put another way, the presenter will have a unique, unambiguous, parameterless method
The view you are creating must implement the interface. In Web Forms, a view is a Web page. So here’s the skeleton of default.aspx:
Just like the controller in ASP.NET MVC, the presenter is a simple class in which all dependencies are (or at least, should be) injected explicitly. The class holds no significant state. The presenter lifetime is usually bound to the view.
A common way of implementing MVP entails that the page (for example, the view) gets a new instance of the presenter for each request. You typically create the presenter instance in Page_Load, as shown here:
In summary, a Web Forms page designed around the MVP pattern is a class that implements a given view interface and holds an instance of a presenter class. What’s the purpose of the presenter instance?