Recognize web design patterns

xiaoxiao2021-03-06  57

Recognize web design patterns

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

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"; // Make sure the database connection // Connection string is stored in Web .Config file is easy to modify using (SqlConnection conn = new SqlConnection (ConfigurationSettings.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 and text domain, value domain DROPDOWNLIST.DataSource = Dataset; DropdownList.DataTextField = "portalname"; DropDownList.DataValuefield = "portalid"; dropdownload (}}} // button) 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 (ConfigurationSettings.AppSettings [ "ConnectionString"])) { // Use the value selected by the drop-down list to replace the pending character {0} sqldataadapter dataAdapter = new sqldataadapter (SQL_SELECT (SUBJECT) (SQL_SELECT_SUBJECT, DROPDOWNLIST.SELECT) DVALUE), CONN); DataSet DataSet = New Dataset (); DataAdapter.Fill (DataSet); DataGrid.dataSource = DataSet; DataGrid.Database ();}} The execution result is as shown in the figure, the program will be selected according to the drop-down list box. Finding DataGrid, very typical webform architecture, reflecting the idea of ​​ASP.NET event driver, implementing the interface and code separation. 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 change in the webform is much 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 (SQL_CONNECTION_STRING) ) {SqlDataAdapter dataAdapter = new SqlDataAdapter (sql, conn); DataSet dataSet = new DataSet (); dataAdapter.Fill (dataSet); return dataSet;}} Controller (webForm.aspx.cs): is responsible for conversion of user input private void Page_Load (! IsPostBack) (object sender, System.EventArgs e) {if {// Model method calls to obtain the data source dropDownList.DataSource = SQLHelper.GetPortal (); dropDownList.DataTextField = "portalName"; dropDownList.DataValueField = "portalId" ; DR opDownList.DataBind ();}} private void button_Click (object sender, System.EventArgs e) {dataGrid.DataSource = SQLHelper.GetSubject (dropDownList.SelectedValue); dataGrid.DataBind ();} modified code is very clear, MVC each Division, no change in any module will cause 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. 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 specifying {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 base.render (Writer); // Sub-page Output Writer.write (@" <a href=""http://www.asp.net""> asp.net </a> </ body> </ html> "); // Unified page tail}}</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: "! Hello, World" BasePage // page base class inherit {private void Page_Load (object sender, System.EventArgs e) {Title =; // specified page header if (! IsPostBack) {dropDownList.DataSource = GetPortalDataSource (); // call the base class method dropDownList.DataTextField = "portalName"; dropDownList.DataValueField = "portalId"; dropDownList.DataBind ();}} private void button_Click (object sender, System.EventArgs e) {dataGrid.DataSource = GetSubjectDataSource (DropdownList.Selected (Datagrid.Database);}} It can be seen from thisPage Controller to take over most original Controller's work, making Controller easier, easier to modify (for easy explanation I didn't put controls Placed in Basepage, but you can do that), but with the increase in application complexity, the user needs changes, we can easily make different page types into different base classes, causing excessive inheritance trees; For example, for a shopping cart program, a predetermined page path is required; the path is dynamic for the wizard program (the user's choice is not known 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.</p> <p>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: First in Web.config:</p> <p><! - Specifies the ASPX file that is starting with Dummy -> <httphandlers> <add verb = "*" path = "/ WebPatterns / FrontController / Dummy * .aspx" type = "WebPatterns.frontcontroller.handler, WebPatterns "/> </ httphandlers> <! - Specify a page mapping block named FrontControllermap, handed over the URLMAP class processing, the program will find the corresponding URL as the final execution path based on Key, you can define multiple keys url value pairs -> <configSections> <section name = "FrontControllerMap" type = "WebPatterns.FrontController.UrlMap, WebPatterns"> </ section> </ configSections> <FrontControllerMap> <entries> <entry key = "/ WebPatterns / FrontController / Dummywebform.aspx "URL =" / WebPatterns / FrontController / ActWebform.aspx "/>. . . </ Entries> </ FrontControllerMap> Review webForm.aspx.cs: private void button_Click (object sender, System.EventArgs e) {Response.Redirect ( "? DummyWebForm.aspx requestParm =" dropDownList.SelectedValue);} when the program is executed when ProcessRequest here will be based on the definition of a trigger event Web.Config in the class Handler: Handler.cs: public class Handler: IHttpHandler {public void ProcessRequest (HttpContext context) {Command command = CommandFactory.Make (context.Request.Params) Command.execute (context);} public bool isreusable {get {return true;}}}</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 {public static Command Make (NameValueCollection parms) {string requestParm = parms [ "requestParm"]; Command command = null; // get different Command object switch (requestParm) {case "1" according to the input parameters: command = new FirstPortal (); break; case "2": command = new SecondPortal (); break; default: command = new FirstPortal (); break;} return command;}} public interface Command {void Execute (HttpContext context);} public abstract class RedirectCommand: Command {// get the key and key Web.Config url defined in the code-based private UrlMap map UrlMap see the download package = UrlMap.SoleInstance; protected abstract void OnExecute (HttpContext context); public Void execute (httpContext context) {onexecute (context); // submitted to the specific processing page string url = string.format ("{0}? {1}", map.map according to the key and URL key value. Request.Url.AbsolutePath], context.Request.Url.Query); context.Server.Transfer (url);}} public class FirstPortal: RedirectCommand {protected override void OnExecute (HttpContext context) {// Add items in the input parameters Portalid for page processing C ontext.Items [ "portalId"] = "1";}} public class SecondPortal: RedirectCommand {protected override void OnExecute (HttpContext context) {context.Items [ "portalId"] = "2";}} Finally ActWebForm.aspx In .CS: DataGrid.DataSource = GetSubjectDataSource (httpContext.current.Items ["portalid"]. TOSTRING ()); DataGrid.Database (); The above example shows how to concentrate and process all requests via Front Controller, it use CommandFactory to determine the specific operations to be executed, whether the method and objects do, Handler only call the Command object's Execute method, and you can add additional commands without modifying your handler. 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. 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 () {dataset dataset; if (httpContext.current.cache ["select_portal_cache"]! = null) {// If data exists, DataSet = (DataSet) httpcontext.current.cache [" SELECT_PORTAL_CACHE "];} else {/ / otherwise removed from the database and inserted into the cache, set the absolute expiration time to 3 minutes DataSet = getDataSet; httpContext.current.cache.insert (" SELECT_PORTAL_CACHE ", Dataset, NULL Datetime.now.addminutes (3), timespan.zero;} Return DataSet;</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.</p> <p>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-113864.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="113864" 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.044</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 = 'icE8fMrMIyUYAzZQNmCy_2B67kxgwt05Fs136IcYz4obtnG7bloQ2shw4tVBXd1jyy47R4c17i3osorDcLk5Vesg_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>