Recognize web design patterns

xiaoxiao2021-03-06  16

Recognize web design patterns

This article is published in "Program Spring and Autumn" 2004 1

Summary

This article describes some basic methods and points for improving WebForm programming under the .NET framework.

Keyword

Design mode, ASP.NET, Webform, MVC, Page Controller, Front Controller, Page Cache

table of Contents

 Introduction

 Classic WebForm architecture

 Design mode

 WebForm in MVC mode

 WebForm in Page Controller mode

 Webform in Front Controller mode

 Webform in Page Cache mode

 Reference resources

 Download address

 Author information

introduction

I remember that Microsoft has just launched the ASP.NET, giving people the shock is that the development web program is no longer a traditional web page, and like the application application, the Microsoft is called WebForm. But two years later, there are quite a few developers still extend the idea of ​​writing scripts to build another WebForm, without playing the advantage of ASP.NET, and this article hopes to inspire some new ideas to inspire readers through instances. .

Due to limited space, this paper is impossible to show the reader to the reader's WebForm through a complex web application, but if only a small program does not use the mode. For ease of understanding, I hope you can imagine it into a small module in a large system (if the code is part of the large system, it is very important).

The download address of all source programs is given at the end of this article.

Classic WebForm architecture

First, look at a simple application, the database is designed below, Portal is a parent table of the Subject, a pair of associations by PortalID, and the program needs to display different Subject lists according to Portalid.

Follow us to write WebForm's general habits, first drag and drop a DROPDOWNLIST on the page, a DataGrid, a Button control:

WebForm.aspx:

The core code written by hiding the function using the VS.NET code is as follows:

Rear code (WebMM.ASPX.CS):

// Page initialization event

Private Void Page_Load (Object Sender, System.EventArgs E)

{

IF (! ispostback)

{

String SQL_SELECT_PORTAL = "SELECT * from Portal";

// Use using to ensure the release database connection

/ / Connection string is placed in a web.config file to facilitate modification

Using (SqlConnection Conn = New SqlConnection (ConfigurationSttings.AppSettings ["Connectionstring"]) {

SqlDataAdapter DataAdapter = New SqlDataAdapter (SQL_SELECT_PORTAL, CONN);

DataSet DataSet = New DataSet ();

DataAdapter.Fill (DataSet);

/ / Set the data source of the drop-down list with text domain, value domain

DropdownList.DataSource = DataSet;

DropDownList.DataTextField = "PortalName";

DropdownList.DataValuefield = "portalid";

DropDownList.DATABIND ();

}

}

}

// Button's Click event

Private void Button_Click (Object Sender, System.Eventargs E)

{

String SQL_SELECT_SUBJECT = "SELECT * from Subject WHERE Portalid = {0}";

Using (SqlConnection Conn = New SqlConnection (ConfigurationStings.AppSettings ["Connectionstring"]))

{

// Replace the pending character {0} in the SQL statement with the value selected by the drop list.

SqldataAdapter DataAdapter = new sqldataadapter (String.Format (SQL_SELECT_SUBJECT, DROPDOWNLIST.SELECTEDVALUE), CONN);

DataSet DataSet = New DataSet ();

DataAdapter.Fill (DataSet);

DataGrid.datasource = dataset;

DataGrid.databind ();

}

}

The execution result is as shown in the figure, the program will bind DataGrid according to the value selected by the drop-down list box, which reflects the idea of ​​ASP.NET event driver, and implements the separation of the interface and code. But take a closer look, you can find a few questions:

 Repeat the code of the database, duplicate code is the absolute "bad taste" in software development, often because of some reason, when you modify a code, forget to change the same code, thus leave the program The hidden danger of bug.

 The rear code is completely dependent on the interface. The changes in the WebForm are far greater than the change in data storage structure and access. When the interface changes, you will have to modify the code to accommodate the new page, it is possible to rewrite the whole Set code.

 The rear code not only handles the user's input but also the processing of the data. If the demand changes, for example, you need to change the processing method of data, then you will almost rewrite the entire post code.

A excellent design requires every module, each method is only focused on doing something, such a structure is clear, easy to modify, after all, the demand for the project is constantly changing, "The only constant is the change itself" Good procedures must be prepared for changes, avoid "moving the whole body", so we must find ways to solve the above problems, let us take a look at the design model.

Design Patterns

Design patterns describe a continuous repeated problem and a core solution for this issue, which is a successful architecture, design and implementation plan, is a summary of experience. The concept of design patterns came earlier from Western architecture, but the most successful case was first pushed in ancient China's "36). WebForm in MVC mode

The MVC mode is a basic design pattern for separating user interface logic to business logic, which divides data processing, interface, and user behavior control: Model-View-Controller.

 MODEL: responsible for the current application data acquisition and change and related business logic

 View: Responsible for display information

 Controller: Responsible for collecting input to transformation users

VIEW and Controller are dependent on Model, but Model does not depend on View, nor does it depend on Controller, which is one of the main advantages of separation, so Model can establish and test separately for code multiplexing, View and Controller only need MODEL provides data, they will not know, nor is it that data is stored in SQL Server or any place in an Oracle database.

According to the idea of ​​MVC mode, the back code of the above example can be split into Model and Controller, with a special class to process data, and the rear code is only responsible for converting the user's input as Controller, and the modified code is:

Model (SQLHELPER.CS): Pack all the operations of the database.

Private static string SQL_SELECT_PORTAL = "Select * from portal";

Private static string sql_select_subject = "SELECT * from Subject where portalid = {0}";

Private static string SQL_CONNECTION_STRING = ConfigurationSettings.AppSettings ["Connectionstring"];

Public Static Dataset getPortal ()

{

Return getDataSet (SQL_SELECT_PORTAL);

}

Public Static DataSet GetSubject (String Portalid)

{

Return getDataSet (String.Format (SQL_SELECT_SUBJECT, PORTALID);

}

Public Static DataSet getDataSet (String SQL)

{

Using (SqlConnection Conn = New SqlConnection))

{

SqlDataAdapter DataAdapter = New SqldataAdapter (SQL, CONN);

DataSet DataSet = New DataSet ();

DataAdapter.Fill (DataSet);

Return DataSet;

}

}

Controller (WebForm.aspx.cs): Responsible for transforming users' input

Private Void Page_Load (Object Sender, System.EventArgs E)

{

IF (! ispostback)

{

// Call the MODEL method to get the data source

DropdownList.DataSource = SQLHELPER.GETPORTAL ();

DropDownList.DataTextField = "PortalName";

DropdownList.DataValuefield = "portalid";

DropDownList.DATABIND ();

}

}

Private void Button_Click (Object Sender, System.Eventargs E)

{

DataGrid.datasource = SQLHELPER.GETSUBJECT (DropDownList.SelectedValue);

DataGrid.databind ();

}

The modified code is very clear, and the M-V-C has made the other module rewriting causes changes in other modules, similar to the DOC / View structure in the MFC. But if the same structure has a lot of procedures, we need to do some unified controls, such as user identity, unified interface style, etc .; or you want Controller to separately separate, not involving Model layers in Controller Code. At this time, just rely on the MVC mode, you will be a bit of strength, then take a look at the Page Controller mode below.

WebForm in Page Controller

The MVC mode mainly focuses on the separation between Model and View, and less concerned about Controller (in the above MVC mode, we only leave Model and Controller, do not process Controller), but based on In WebForm's applications, View and Controller have been separated (the display is performed in the client browser), and the controller is a server-side application; while different user operations may cause different Controller policies, the application must be based on One page and user triggering events to perform different operations; there are many webforms that require a unified interface style, and if it is not possible to generate duplicate code, it is necessary to make CONTROLLER more carefully divided.

Page Controller Mode Based on the MVC mode, use a public page base class to unify the like, such as HTTP requests, interface style, etc.

Traditional WebForm typically inherits from the System.Web.ui.page class, and the implementation of the Page Controller is that all WebForm inherits the custom page base class, as shown:

With the custom page base class, we can unify the page request, extract all related data, call all updates to Model and forward the request to the View, and easily implement the unified page style, and the logic of the Controller it derived will change It is simpler, more specific.

Let's take a look at the specific implementation of Page Controller:

Page controller (Basepage.cs):

Public class basepage: System.Web.ui.page

{

Private string_title;

Public String Title // Page title, responsible for subscribers

{

get

{

Return_title;

}

set

{

_title = value;

}

}

Public DataSet GetportalDataSource ()

{

Return SQLHELPER.GETPORTAL ();

}

Public DataSet GetSubjectDataSource (String Portalid)

{

Return Sqlhelper.getsubject (portalid);

Protected Override Void Render (HTMLTextWriter Writer)

{

Writer.write (" " title "</ title> </ head> <body>"); // Unified page head</p> <p>Base.Render (Writer); // Output of subpage</p> <p>Writer.write (@ "<a href=""http://www.asp.net""> asp.net </a> </ body> </ html>"); // unified page</p> <p>}</p> <p>}</p> <p>Now it encapsulates the functionality of Model, achieving a unified page title and page end, subclasses only need to call directly:</p> <p>Modified Controller (WebForm.aspx.cs):</p> <p>Public class webform: basepage // inherited page base class</p> <p>{</p> <p>Private Void Page_Load (Object Sender, System.EventArgs E)</p> <p>{</p> <p>Title = "Hello, World!"; // Specify page title</p> <p>IF (! ispostback)</p> <p>{</p> <p>DropDownList.DataSource = getportalDataSource (); // Method for calling the base class</p> <p>DropDownList.DataTextField = "PortalName";</p> <p>DropdownList.DataValuefield = "portalid";</p> <p>DropDownList.DATABIND ();</p> <p>}</p> <p>}</p> <p>Private void Button_Click (Object Sender, System.Eventargs E)</p> <p>{</p> <p>DataGrid.DataSource = getSubjectDataSource (DropDownList.SelectedValue);</p> <p>DataGrid.databind ();</p> <p>}</p> <p>}</p> <p>From now on, it can be seen that most of the original Controller work, making Controller more simple, easier to modify (for easy explanation, I didn't put the control in Basepage, but you can do that), but as follows Using complexity of complexity, the change of user needs, we can easily form different page types into different base classes, causing deep inheritance trees; for example, for a shopping cart program, you need to predefined a good page path; The wizard program is dynamic (no choice for the user in advance).</p> <p>In the face of these applications, just use Page Controller or not enough, then look at Front Controller mode.</p> <p>Webform in Front Controller mode</p> <p>Page Controller's implementation requires creating code for the public part of the page in the base class, but over time, the demand will have a large change, sometimes to increase the non-public code, so the base class will continue to increase. You may create a deeper inheritance hierarchy to delete conditional logic, so that we are difficult to reconstruct it, so you need to further study Page Controller.</p> <p>The Front Controller is divided into two parts: Handler and Command trees, Handler processes all public logic, and receives HTTP POST or GET requests and related Parameters and select the correct command object based on the input parameters, then pass control to the Command object, which is completed later, where we will use the Command mode. Command mode By making a request itself into an object to request a request, this object can be stored and passed like other objects. The key to this mode is an abstract Command class, which defines an execution The simplest form is an abstract execute operation, the specific Command subclass uses the recipient as an instance variable, and implements the execute operation, specifies the action taken by the recipient, and the recipient has the request required. Specific information.</p> <p>Because the Front Controller mode is more complicated than the above two modes, let's take a look at the class diagram of the example:</p> <p>For the principle of Handler, please check MSDN, don't talk about it, let's take a look at the specific implementation of Front Controller mode:</p> <p>First define in Web.config:</p> <p><! - Specifies the ASPX file that starts with Dummy to hand over the Handler processing -></p> <p><httphandlers></p> <p><add verb = "*" path = "/ WebPatterns / FrontController / Dummy * .aspx" Type = "WebPatterns.frontcontroller.Handler, WebPatterns" /></p> <p></ httphandlers></p> <p><! - Specify the page map of FrontControllermap, handed over the URLMAP class processing, the program will find the corresponding URL as the final execution path according to Key, you can define multiple key and URL key values ​​-></p> <p><configsections></p> <p><section name = "frontControllermap" type = "WebPatterns.frontcontroller.urlmap, WebPatterns"> </ section></p> <p></ configsections></p> <p><FrontControllermap></p> <p><entries></p> <p><entry key = "/ WebPatterns / FrontController / Dummywebform.aspx" URL = "/ WebPatterns / FrontController / ActWebform.asp" /></p> <p>. . .</p> <p></ entry></p> <p></ FrontControllermap></p> <p>Modify WebForm.aspx.cs:</p> <p>Private void Button_Click (Object Sender, System.Eventargs E)</p> <p>{</p> <p>Response.Redirect ("DummyWebform.aspx? RequestParm =" DropdownList.SelectedValue);</p> <p>}</p> <p>The ProcessRequest event of the class handler will be triggered according to the definition of the definition in Web.config when the program is executed.</p> <p>Handler.cs:</p> <p>Public class handler: httphandler {</p> <p>Public void processRequest (httpcontext context)</p> <p>{</p> <p>Command command = commandFactory.make (context.Request.Params);</p> <p>Command.execute (context);</p> <p>}</p> <p>Public Bool IsReusable</p> <p>{</p> <p>get</p> <p>{</p> <p>Return True;</p> <p>}</p> <p>}</p> <p>}</p> <p>It will call the Make method of class commandFactory to process the received parameters and return a Command object, followed by calling the Command object's Execute method to submit the process-behind parameters to the specific processing page.</p> <p>Public Class CommandFactory</p> <p>{</p> <p>Public Static Command Make (NameValueCollection PARMS)</p> <p>{</p> <p>String RequestParm = PARMS ["RequestParm"];</p> <p>Command command = NULL;</p> <p>/ / Get different Command objects according to the input parameters</p> <p>Switch (RequestParm)</p> <p>{</p> <p>Case "1":</p> <p>Command = new firstportal ();</p> <p>Break;</p> <p>Case "2":</p> <p>Command = new secondportal ();</p> <p>Break;</p> <p>DEFAULT:</p> <p>Command = new firstportal ();</p> <p>Break;</p> <p>}</p> <p>Return Command;</p> <p>}</p> <p>}</p> <p>Public Interface Command</p> <p>{</p> <p>Void Execute (httpcontext context);</p> <p>}</p> <p>Public Abstract Class RedirectCommand: Command</p> <p>{</p> <p>// Get the key and URL key value defined in web.config, the URLMap class see the code in the download package</p> <p>Private urlmap map = urlmap.soleinstance;</p> <p>Protected Abstract Void Onexecute (HttpContext Context);</p> <p>Public void Execute (httpcontext context)</p> <p>{</p> <p>Onexecute (Context);</p> <p>/ / According to the key value of the key and the URL key, the page submitted to the specific processing</p> <p>String url = string.format ("{0}? {1}", map.map [context.request.ur.absolutepath], context.request.ur.query;</p> <p>Context.Server.Transfer (URL);</p> <p>}</p> <p>}</p> <p>Public Class Firstportal: RedirectCommand</p> <p>{</p> <p>Protected Override Void Onexecute (HTTPCONTEXT Context)</p> <p>{</p> <p>/ / Add Item PortalID in the input parameter to page processing</p> <p>Context.Items ["Portalid"] = "1";</p> <p>}</p> <p>}</p> <p>Public Class Secondportal: RedirectCommand</p> <p>{</p> <p>Protected Override Void Onexecute (HTTPCONTEXT Context)</p> <p>{</p> <p>Context.Items ["Portalid"] = "2";</p> <p>}</p> <p>}</p> <p>Finally in Actwebform.aspx.cs:</p> <p>DataGrid.datasource = GetSubjectDataSource (httpContext.current.items ["portalid"]. TOSTRING ()); DataGrid.Database ();</p> <p>The above example shows how to concentrate and process all requests through the Front Controller, which uses CommandFactory to determine the specific operations to be executed, whether the method and objects do, Handler only call the Execute method of the Command object, you can do not modify your handler Add additional commands. It allows the user to see the actual page, and when the user enters a URL, then the system will map it to a specific URL according to the web.config file, which allows the programmer to have more flexibility, you can also get Page A indirect operating layer in which the Controller is implemented.</p> <p>We will use Front Controller mode for fairly complex web applications, which typically need to replace the Controller built into the page to customize Handler, we can even do not need pages in Front Controlra mode, but due to its own implementation, possibly It will bring some troubles to the implementation of business logic.</p> <p>The above two Controller models are more complex WebForm applications. The complexity is greatly improved relative to the application that directly handles the user input, and performance must also decrease. We finally look at the performance of programs. Mode: Page Cache mode.</p> <p>WEBFORM in Page Cache</p> <p>Almost all of WebForm is very frequent, there are very few applications that have changed, and there is quite a lot of content for WebForm visitors, so we can try to save WebForm or some of the same content. Server memory is a period of time to speed up the response speed.</p> <p>This mode is very simple, just join:</p> <p><% @ Outputcache duration = "60" VarybyParam = "none"%>,</p> <p>This means that the page will expire after 60 seconds, that is, all visitors within this 60 seconds are the same, but the response speed is greatly improved, just like a static HTML page.</p> <p>Maybe you just want to save some of the content instead of wanting to save the entire page, then we return to the SQLHELPER.CS in the MVC mode, I have made a little modification of it:</p> <p>Public Static Dataset getPortal ()</p> <p>{</p> <p>DataSet DataSet;</p> <p>IF (httpContext.current.cache ["SELECT_PORTAL_CACHE"]! = NULL)</p> <p>{</p> <p>// Directly removed if the data is present in the cache</p> <p>DataSet = (Dataset) httpcontext.current.cache ["SELECT_PORTAL_CACHE"];</p> <p>}</p> <p>Else</p> <p>{</p> <p>/ / Otherwise, from the database and insert into the cache, set the absolute expiration time to 3 minutes</p> <p>DataSet = getDataSet (SQL_SELECT_PORTAL);</p> <p>HttpContext.current.cache.insert ("SELECT_PORTAL_CACHE", Dataset, Null, DateTime.now.addminutes (3), Timespan.zero;</p> <p>}</p> <p>Return DataSet;</p> <p>}</p> <p>Here, select_portal_cache as the Cache key, and remove the contents of GetDataSet (SQL_SELECT_PORTAL) as the value of Cache. In addition, in addition to the program first call, the database operation is not performed in the Cache expiration time, which is also greatly improved by the program's response capability. summary</p> <p>Since the introduction of the .NET framework, it has greatly improved its strength in enterprise applications, and it can be said that it is not exaggerated. Net has caught up with Java's pace and later hosted This article shows the reader to read some basic knowledge required to implement Web design patterns under the .NET framework, hoping to play the role of a throwing jade.</p> <p>Reference resource</p> <p>Http://msdn.microsoft.com/architecture/patterns/esp/default.aspx</p> <p>download link</p> <p>author information</p> <p>Yuan Jian</p> <p>Microsoft ASP.NET MVP</p> <p>http://blog.joycode.com/goodidea</p> <p>December 6, 2003</p></div><div class="text-center mt-3 text-grey"> 转载请注明原文地址:https://www.9cbs.com/read-42001.html</div><div class="plugin d-flex justify-content-center mt-3"></div><hr><div class="row"><div class="col-lg-12 text-muted mt-2"><i class="icon-tags mr-2"></i><span class="badge border border-secondary mr-2"><h2 class="h6 mb-0 small"><a class="text-secondary" href="tag-2.html">9cbs</a></h2></span></div></div></div></div><div class="card card-postlist border-white shadow"><div class="card-body"><div class="card-title"><div class="d-flex justify-content-between"><div><b>New Post</b>(<span class="posts">0</span>) </div><div></div></div></div><ul class="postlist list-unstyled"> </ul></div></div><div class="d-none threadlist"><input type="checkbox" name="modtid" value="42001" checked /></div></div></div></div></div><footer class="text-muted small bg-dark py-4 mt-3" id="footer"><div class="container"><div class="row"><div class="col">CopyRight © 2020 All Rights Reserved </div><div class="col text-right">Processed: <b>0.040</b>, SQL: <b>9</b></div></div></div></footer><script src="./lang/en-us/lang.js?2.2.0"></script><script src="view/js/jquery.min.js?2.2.0"></script><script src="view/js/popper.min.js?2.2.0"></script><script src="view/js/bootstrap.min.js?2.2.0"></script><script src="view/js/xiuno.js?2.2.0"></script><script src="view/js/bootstrap-plugin.js?2.2.0"></script><script src="view/js/async.min.js?2.2.0"></script><script src="view/js/form.js?2.2.0"></script><script> var debug = DEBUG = 0; var url_rewrite_on = 1; var url_path = './'; var forumarr = {"1":"Tech"}; var fid = 1; var uid = 0; var gid = 0; xn.options.water_image_url = 'view/img/water-small.png'; </script><script src="view/js/wellcms.js?2.2.0"></script><a class="scroll-to-top rounded" href="javascript:void(0);"><i class="icon-angle-up"></i></a><a class="scroll-to-bottom rounded" href="javascript:void(0);" style="display: inline;"><i class="icon-angle-down"></i></a></body></html><script> var forum_url = 'list-1.html'; var safe_token = 'POCFXa2nlYp3Qq2c8c_2FODVoc_2FL4_2FcZaW0pm_2Bi9xjW6eNVDAxfs33AjV_2BWqBHFF87g_2BMNsi4A5XdP_2BwF_2FHfiKnA_3D_3D'; var body = $('body'); body.on('submit', '#form', function() { var jthis = $(this); var jsubmit = jthis.find('#submit'); jthis.reset(); jsubmit.button('loading'); var postdata = jthis.serializeObject(); $.xpost(jthis.attr('action'), postdata, function(code, message) { if(code == 0) { location.reload(); } else { $.alert(message); jsubmit.button('reset'); } }); return false; }); function resize_image() { var jmessagelist = $('div.message'); var first_width = jmessagelist.width(); jmessagelist.each(function() { var jdiv = $(this); var maxwidth = jdiv.attr('isfirst') ? first_width : jdiv.width(); var jmessage_width = Math.min(jdiv.width(), maxwidth); jdiv.find('img, embed, iframe, video').each(function() { var jimg = $(this); var img_width = this.org_width; var img_height = this.org_height; if(!img_width) { var img_width = jimg.attr('width'); var img_height = jimg.attr('height'); this.org_width = img_width; this.org_height = img_height; } if(img_width > jmessage_width) { if(this.tagName == 'IMG') { jimg.width(jmessage_width); jimg.css('height', 'auto'); jimg.css('cursor', 'pointer'); jimg.on('click', function() { }); } else { jimg.width(jmessage_width); var height = (img_height / img_width) * jimg.width(); jimg.height(height); } } }); }); } function resize_table() { $('div.message').each(function() { var jdiv = $(this); jdiv.find('table').addClass('table').wrap('<div class="table-responsive"></div>'); }); } $(function() { resize_image(); resize_table(); $(window).on('resize', resize_image); }); var jmessage = $('#message'); jmessage.on('focus', function() {if(jmessage.t) { clearTimeout(jmessage.t); jmessage.t = null; } jmessage.css('height', '6rem'); }); jmessage.on('blur', function() {jmessage.t = setTimeout(function() { jmessage.css('height', '2.5rem');}, 1000); }); $('#nav li[data-active="fid-1"]').addClass('active'); </script>