Implement Model-View-controller in ASP. NET

Source: Internet
Author: User

Implementation Policy

To explain how to implement it in ASP. NETModel-View-ControllerMode, and describes the benefits of Separating Models, views, and controller roles in the software, the following example refactor a single page solution without separating all three roles into a solution for separating these three roles. The sample application is a webpage with a drop-down list (1), which displays records stored in the database.

Select a specific record from the drop-down list and click Submit. Then, the application retrieves information about all the tracks in the record from the database and displays the results in a table. All three solutions described in this mode implement the same functionality.

Single ASP. NET page

You can implement this page in ASP. NET in many ways. The simplest and most direct method is to put all the content in a file named "solution. aspx", as shown in the following code example:

<% @ Import namespace = "system. data "%> <% @ import namespace =" system. data. sqlclient "%> <HTML> 

This file implements all three roles in this mode, but does not separate them into different files or classes. View roles are represented by page generation Code related to HTML. This page uses the bound data control implementation to display the returned data from the databaseDatasetObject. Model role inPage_loadAndSubmitbtn_clickFunction. The Controller role is not expressed directly, but hidden in ASP. NET. See "Page controller"Page Controller". This page is updated when a user sends a request. Model-View-controller describes it as a passive controller. ASP. NET implements the Controller role, but the programmer is responsible for connecting the action to the event that the Controller will respond. In this example, the Controller callsPage_loadFunction. After you click "Submit", the Controller callsSubmitbtn_clickFunction.

This webpage is simple and complete independently. This implementation is very useful. It is a very good starting point when the application is small and does not change frequently. However, if one or more of the following situations occur during development, consider changing this method.

  • We hope to increase concurrency and reduce the possibility of errors.You may want different people to write view code and model code to improve concurrency and limit the possibility of errors. For example, if all the code is on a webpage, developers may accidentally change the source code of some databases when changing the DataGrid format. This error is not found until you view this page again, because it is compiled only when you view this page again.

  • You want to reuse the database access code on multiple web pages.In the current implementation, you cannot reuse any code on other web pages without repeating the code. Repeated code is difficult to maintain, because if the database code is changed, you must modify all the web pages of the database.

    To solve some of these problems, ASP. NET introduces the code hiding function.

    Code hidden refactoring

    Using the code hiding function of the Microsoft Visual Studio. NET development system, you can easily separate the presentation (View) code from the model-controller code. Each ASP. NET page has a mechanism that allows you to call methods from a web page in a separate class. This mechanism is provided through Visual Studio. NET and has many advantages, such as Microsoft intelliisense technology. When you use the code hiding function to implement a webpage, you can use intelliisense to display the list of available methods of the objects used in the code after the webpage. Intelliisense does not apply to. aspx pages.

    The following is the same example, but this time ASP. NET is implemented using the code hiding function.

    View

    Now, the code is in a separate file named solution. aspx:

    <% @ Page Language = "C #" codebehind = "solution. aspx. CS "autoeventwireup =" false "inherits =" solution "%> <HTML> 

    Most of this Code is similar to the code used in the first implementation. The main difference lies in the first line:

     <%@ Page language="c#" Codebehind="Solution.aspx.cs"    AutoEventWireup="false" Inherits="Solution" %> 

    This row tells the ASP. NET environment that the Code hiding class implements the methods referenced on this page. Because this page does not have any code to access the database, you do not need to modify this page even if the database access code is changed. People familiar with the user interface design can modify the code without any errors in the database access code.

     

    Model-Controller

    The second part of the solution is to hide the webpage with the following code:

    Using system; using system. data; using system. data. sqlclient; public class solution: system. web. UI. page {protected system. web. UI. webcontrols. button submit; protected system. web. UI. webcontrols. dataGrid mydatagrid; protected system. web. UI. webcontrols. dropdownlist recordingselect; private void page_load (Object sender, system. eventargs e) {If (! Ispostback) {string selectcmd = "select * from recording"; sqlconnection myconnection = new sqlconnection ("Server = (local); database = recordings; trusted_connection = yes "); sqldataadapter mycommand = new sqldataadapter (selectcmd, myconnection); dataset DS = new dataset (); mycommand. fill (DS, "Recording"); recordingselect. datasource = Ds; recordingselect. datatextfield = "title"; recordingselect. datavalu Efield = "ID"; recordingselect. databind () ;}} void submitbtn_click (Object sender, eventargs e) {string selectcmd = string. format ("select * from track where recordingid = {0} order by ID", (string) recordingselect. selecteditem. value); sqlconnection myconnection = new sqlconnection ("Server = (local); database = recordings; trusted_connection = yes"); sqldataadapter mycommand = new sqldataadapter (selectcm D, myconnection); dataset DS = new dataset (); mycommand. fill (DS, "track"); mydatagrid. datasource = Ds; mydatagrid. databind () ;}# region web form designer generated code override protected void oninit (eventargs e) {// codegen: Asp.. NET web form designer. // Initializecomponent (); base. oninit (E );}////// The designer supports the required methods-do not use the code editor to modify the content of this method. ///Private void initializecomponent () {This. submit. click + = new system. eventhandler (this. submitbtn_click); this. load + = new system. eventhandler (this. page_load) ;}# endregion}

    This code has been moved from a single ASP. NET page to a separate file. Several syntax changes are required to link two entities together. The name of the member variable defined in the class is the same as that referenced in the solution. aspx file. What must be explicitly defined is, on the other hand, how the Controller links events that respond to the operations that must be performed. In this example,InitializecomponentMethod links two events. The first one isLoadEvent, which is linkedPage_loadFunction. The second one isClickEvent, triggered after you click the submit buttonSubmitbtn_clickFunction execution.

    The Code hiding function is a good mechanism that separates view roles from model roles and controller roles. This feature may not be suitable when you need to reuse the code in the Code hiding class on other web pages. From a technical point of view, it is possible to reuse code to hide the code in a webpage, but we do not recommend that you do so, because this will increase the correlation between all webpages of the shared code hiding class.

    Model-View-controller Reconstruction

    To solve the last problem, we need to further separate the model code from the Controller. The view code is the same as the code in the previous implementation.

    Model

    The following code example describes the model and is only related to the database. It does not contain any view-related code (dependent on ASP. NET code ):

     using System;using System.Collections;using System.Data;using System.Data.SqlClient;public class DatabaseGateway{   public static DataSet GetRecordings()   {      String selectCmd = "select * from Recording";      SqlConnection myConnection =          new SqlConnection(            "server=(local);database=recordings;Trusted_Connection=yes");      SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd, myConnection);      DataSet ds = new DataSet();      myCommand.Fill(ds, "Recording");      return ds;   }   public static DataSet GetTracks(string recordingId)   {      String selectCmd =          String.Format(         "select * from Track where recordingId = {0} order by id",         recordingId);      SqlConnection myConnection =          new SqlConnection(            "server=(local);database=recordings;Trusted_Connection=yes");      SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd, myConnection);      DataSet ds = new DataSet();      myCommand.Fill(ds, "Track");      return ds;   } 

    Currently, this is the only database-dependent file. This class isTable Data GatewayA good example of the mode.Table Data GatewayContains all the SQL code used to access a single table or view: Select, insert, update, and delete. Other code calls its method to interact with the database. [Fowler03]

    Controller

    This refactoring uses the code hiding function to rewrite the model code to adapt to the Data Controls on the web page and map the events forwarded by the Controller to specific operation methods. Because the MODEL returned hereDatasetObject. Similar to view code, this code does not depend on how data is retrieved from a database.

    Using system; using system. data; using system. collections; using system. web. UI. webcontrols; public class solution: system. web. UI. page {protected system. web. UI. webcontrols. button submit; protected system. web. UI. webcontrols. dataGrid mydatagrid; protected system. web. UI. webcontrols. dropdownlist recordingselect; private void page_load (Object sender, system. eventargs e) {If (! Ispostback) {dataset DS = databasegateway. getrecordings (); recordingselect. datasource = Ds; recordingselect. datatextfield = "title"; recordingselect. datavaluefield = "ID"; recordingselect. databind () ;}} void submitbtn_click (Object sender, eventargs e) {dataset DS = databasegateway. gettracks (string) recordingselect. selecteditem. value); mydatagrid. datasource = Ds; mydatagrid. databind () ;}# Region Web Form Designer generated code override protected void oninit (eventargs e) {// codegen: This call is required by the ASP. NET web forms designer. // Initializecomponent (); base. oninit (E );}////// The designer supports the required methods-do not use the code editor to modify the content of this method. ///Private void initializecomponent () {This. submit. click + = new system. eventhandler (this. submitbtn_click); this. load + = new system. eventhandler (this. page_load) ;}# endregion}

    Test

    By separating the model from the ASP. NET environment, it is easier to test the model code. To test this code in an ASP. NET environment, you must test the output of this process. This means you need to read HTML and check whether it is correct. This process is lengthy and prone to errors. By separating the model to run without ASP. NET, you can avoid this lengthy process and test the Code separately. The following is a sample unit test of the Model Code in nunit (http://nunit.org:

     using System;using NUnit.Framework;using System.Collections;using System.Data;using System.Data.SqlClient;[TestFixture]public class GatewayFixture{   [Test]   public void Tracks1234Query()   {      DataSet ds = DatabaseGateway.GetTracks("1234");      Assertion.AssertEquals(10, ds.Tables["Track"].Rows.Count);   }   [Test]   public void Tracks2345Query()   {      DataSet ds = DatabaseGateway.GetTracks("2345");      Assertion.AssertEquals(3, ds.Tables["Track"].Rows.Count);   }   [Test]   public void Recordings()   {      DataSet ds = DatabaseGateway.GetRecordings();      Assertion.AssertEquals(4, ds.Tables["Recording"].Rows.Count);      DataTable recording = ds.Tables["Recording"];      Assertion.AssertEquals(4, recording.Rows.Count);      DataRow firstRow = recording.Rows[0];      string title = (string)firstRow["title"];      Assertion.AssertEquals("Up", title.Trim());   }}  

    Result Context

    Implementing MVC in ASP. NET has the following advantages and disadvantages:

    Advantages

  • Reduced dependency. Using ASP. NET pages, programmers can implement methods within a Web page. As shown in "A single ASP. NET page", this is useful for prototypes and small short-term applications. As the page complexity increases, or the need to share code between webpages increases, separating all parts of the Code becomes more useful.

  • Reduce code duplication.DatabasegatewayClassGetrecordingsAndGettracksThe method can now be used by other web pages. In this way, you do not need to copy the method to multiple views.

  • Separation of duties and Problems. The skills used to modify ASP. NET pages are different from those used to write database access code. As mentioned above, professionals in various fields can work in parallel by separating views and models.

  • Possibility of Optimization. As mentioned above, dividing responsibilities into specific classes can improve the possibility of optimization. In the preceding example, data is loaded from the database every time a request is sent. Therefore, data can be cached in some cases to improve the overall performance of the application. However, without code separation, it is difficult or impossible to cache data.

  • Testability. By separating models from views, you can test models outside the ASP. NET environment.

    Disadvantages

    Added code and complexity. The preceding example adds more files and code. Therefore, when you have to change all three roles, the Code maintenance cost is increased. In some cases, it is easier to make changes in one file than to make changes in multiple files. Therefore, you must weigh the reason for code separation and the extra cost. If it is a small application, it may not be worth the cost.

    Related Mode

    For more information, see the following modes:

  • Table Data Gateway. This mode is an object that acts as the gateway for the database table. In this mode, one instance processes all roles in the table. [Fowler03]

  • Bound Data Control. This mode is the user interface component bound to the data source. It can be displayed on the screen or on a webpage.

    Thank you

    [Fowler03] Fowler, Martin.Patterns of enterprise application architecture. Addison-Wesley, 2003.

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.