WEB application framework constructive mode based on .NET

zhaozj2021-02-12  137

[Introduction]

This article corresponds to the web representation mode cluster. The first half of the article describes the architecture, design and ASP.NET implementation of the MVC mode, and in a more complex system, then presentation Page Controller and Front. Controller as an addition of MVC implementation, finally, two other two modes of the web representation mode cluster: Intercepting Filter (Filter) and Page Cache mode.

"The first work of the architecture designer is often more concise and clean. He knows that he doesn't understand the work, so he is careful to design it. When he designs the first work, it will make multiple modifications and Grunge. These will be used to "next" ... this second system is the most dangerous system he has designed ... General Trend is that when designing the second system, it will be used in the first work. Be careful to put all the ideas and modifications on one side, resulting in the design of the head. "

-Frederick P. Brooks, Jr. Posted in 1972 The Mythical Man Month (Moon Myth).

The first system established on the web is a simple HTML page that is simply linked together to share documents between the dispersed groups. As the user's usage increases, the dynamic web page entered by the user is increasingly common. Early dynamic pages are typically written in the form of a universal gateway interface (CGI) script. These CGI scripts include not only to determine what contents should be displayed when responding to user input, but also generates HTML. With the increase in more complex logical needs, the demand for richer and more vivid representations is also increased. This increased complexity brings challenges to the CGI programming model.

Soon, the page development means (such as ASP and JSP) appear. These new methods allow developers to simplify the programming model in the HTML side of the developer. When these embedded script applications become more complicated, developers want to separate business logic with representations logically on the page level. To adapt to this request, there is a tag library with help objects and code hidden page policies. Then, a fine frame with dynamically configured site navigation and command scheduling programs appear, but all this is at the expense of increasing complexity. Suppose now has a large number of web represents an option, how to choose the appropriate web to indicate design policies for your application?

Is there a design strategy to adapt to all the situation? Unfortunately, in software design, eliminating excessive redundancy and excessive complexity is a competitive demand, it is difficult to truly do balance between the two. You can start designing work from a simple page that contains embedded scripts, but fast business logic will continue to repeat in each file, resulting in difficulties in maintenance and expansion. By moving the logic into a set of collaborative components, redundancy can be eliminated, but this will increase the complexity of the solution. On the other hand, your design work can be started from the design of the design to provide a flag, dynamic configuration, and command scheduling program, but though can eliminate redundant code, but it will greatly increase the complexity of the system, and this is usually unnecessary.

How to consider all aspects of demand, propose a Web representation strategy for our most suitable application? This requires a choice between complex solutions (support for future changes) and simple solutions (satisfying current requirements), in principle, appropriate increase in cost, and excessive increase cost is not available. . So, less nonsense, we will start from "simple".

MVC (Model - View - Control)

Many computer systems are used to retrieve data from the data store and display it to the user. After the user changes the data, the system stores the update content to the data store. Because the critical information flow occurs between data storage and user interfaces, you may tend to tie the two parts to reduce encoding and improve application performance. However, this seemingly natural method has some big problems. One problem is that changes in user interfaces are often more frequent than changes in data storage systems. Another problem with two parts of the data and user interfaces together is that business applications tend to enter other business logic for far more data transfer features. How to make the web application user interface function to modrew so that you can easily modify each part alone? Model-View-Controller is this mode that implements the separation of functional modules and display modules, making applications more maintainable, scalable, portable, and reused, it was initially Trygve Reenskaug in the 1970s. The last frame is developed by the SmallTalk platform [Fowler03], and there is a very mature pattern that has been formed so far.

MVC solution

Model-View-Controller (MVC) mode is based on user input, dividing the domain modeling, display, and operations into three independent classes [Burbeck92]:

model. The model is used to manage behavior and data of the application domain, and respond to requests issued by its status information (usually from view), and will also respond to the command to change the status (usually from the controller).

view. The view is used to manage information.

Controller. The controller is used to interpret the user's mouse and keyboard input to notify the model and / or the view for the corresponding changes.

Figure 1, a structural relationship between these three objects

Views and controllers are dependent on the model. However, the model does not depend on the view, nor does it depend on the controller. This is one of the main advantages of separation. Such separation allows the model to establish and test in the case of a visual representation function. In many fat client applications, the separation of the view and the controller is secondary, in fact, many user interface frames implement the role as an object. On the other hand, in a web application, the separation of the view (browser) and the controller (handling the HTTP request) is well defined.

Model-View-Controller is an underlying design pattern for separating user interface logic and business logic. Unfortunately, the popularity of this mode has led to many erroneous descriptions. Especially in different contexts, the term "controller" has been used to refer to different things. Fortunately, the emergence of web applications has helped eliminate some unclearness, because the separation of the view and the controller is so obvious.

MVC variant

In Application Programming In Smalltalk-80: How To Use Model-View-Controller (MVC) [Burbeck92], Steve Burbeck describes two variations of MVC: passive models and active models.

The passive model will be used when a controller operates a model in an exclusive manner. The controller will modify the model, then notify the view: The model has changed, and it should be refreshed (see Figure 2). The model in this case is completely independent of the view and controller, which means the model cannot report its status changes. The HTTP protocol is an example of this scheme. The browser does not get an easy way to get an asynchronous update from the server. The browser displays the view and responds to the user input, but it does not detect data changes on the server. If the user explicitly requests refresh, it will be inquiry if the server has changed.

Figure 2, the behavior of the passive model

The active model will be used when the model changes the status without involving the controller. This may happen when other resources are changing data and changes must be reflected in the view. Taking the display quotation machine as an example. You receive stock data from the external source and want to update the view (for example, quotation machine data area and warning window) when stock data changes. Since only the model detects changes to its internal state (when these changes occur, the model must be notified to refresh the display. However, a purpose of using the MVC mode is to make the model independent of the view. If the model must notify the view, you will re-brought the dependency that you want to avoid. Fortunately, OBServer mode [gamma95] provides this mechanism: reminding other objects to pay attention to the status of the status, without led to dependence on these objects. Each view implements the OBServer interface and registers to the model. The model will track a list of all observers made by subscription changes. When the model changes, the model will traverse all registered viewers and inform them. This method is often referred to as "release-subscription". The model does not require specific information about any view. In fact, the controller must do all the work that needs to implement the OBServer interface without the notification controller (for example, enabling or disabling the menu option). For situations where there are many views, it is meaningful to define a plurality of subjects, where each body describes a specific type of model change. Each view can then subscribe to the change type related to the view. Figure 3 shows the structure of the active MVC using OBServer, and how the viewer is separated from the direct reference view.

Figure 3, using the viewer to separate the model and view in the active model

Figure 4 illustrates how the OBServer notifies the view when the model changes. It is a pity that in the unified modeling language (UML) sequence diagram, there is no good way to demonstrate the separation of the model and the view because the figure shows an object's instance instead of the class and interface.

Figure 4, behavior of the active model

Next, we will introduce the ASP.NET implementation of MVC.

MVC ASP.NET implementation

To explain how to implement Model-View-Controller mode in ASP.NET, the benefits of separating models, views, and controller roles in software, the following example reconstructed a single page solution without separating all three roles To separate these three roles. The sample application is a web page with a drop-down list (shown below below), which shows a record stored in the database.

With the Microsoft Visual Studio (R) .NET development system, you can easily divide the representation (view) code from the Model-Controller code. Each ASP.NET page has a mechanism that allows the method to be called from the web page to be implemented in separate classes. This mechanism is provided by Visual Studio .NET, there are many advantages, such as Microsoft IntelliSense (R) technology. When you use the code hidden function to implement a web page, you can use IntelliSense to display the list of available methods of the objects used in the page backed by the page. IntelliSense does not apply to .aspx pages. At the same time, in order to show the separation of Model-Controller, DatabaseGateway is extracted for database operation, so that the complete separation of the three is achieved.

view

<% @ Page language = "c #" codebehind = "solution.aspx.cs" autoeventwireup = "false" inherits = "solution"%> solution </ title> </ head> < Body> <form id = "solution" method = "post" runat = "server"> <h3> recording </ h3> Select Recording: <ask: DropDownList ID = "RecordingSelect" runat = "server" / > <ask: button id = "submit" runat = "server" text = "submit" enableViewState = "false" /> <p /> <asp: datagrid id = "mydataGrid" runat = "server" width = "700" backcolor = "# ccccff" bordercolor = "black" showfooter = "false" cellpadding = "3" cellspacing = "0" font-name = "Verdana" font-size = "8pt" headerstyle-backcolor = "# aaaadd" enableviewstate = "false" /> </ form> </ body> </ html> model</p> <p>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;} control</p> <p>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 {DataSet ds = DatabaseGateway.GetRecordings () (IsPostBack!); 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 codeoverride protected void OnInit (EventArgs e) {//// CODEGEN: this call is ASP.NET Web form Designer It is necessary. //InitializationComponent ();Base.onInit (E );} }/// <summary> /// Designer supports the necessary way - Do not use the code editor to modify the // / this method. /// </ summary> private void InitializeComponent () {this.submit.Click = new System.EventHandler (this.SubmitBtn_Click); this.Load = new System.EventHandler (this.Page_Load);} # endregion} above The example shows the MVC implementation of ASP.NET. In the actual project, business logic is far more than like this, but the above code shows a basic model, which also brings obvious ways to increase code and complexity. Benefits, such as: The reduction in module dependence, decrease in code, duties, and problem separation, testability of code, etc.</p> <p>To now you determine whether you use the Model-View-Controller mode to separate the user interface components of the dynamic web application to the business logic, the application to build will build a web page dynamically, but the current page Navigation is based on static navigation.</p> <p>In a more complex application, how to consider avoiding the repetition of navigation code, even considering the configurable rules to dynamically determine the page navigation, then Page Controller and Front Controller are more complex for the MVC mode. System optimization.</p> <p>We will propose Page Controller and Front Controller as a supplement to the MVC implementation in the next article.</p> <p>Medium complexity optimization --Page Controller (Page Controller)</p> <p>Using the Page Controller mode Accepting input from page requests, calling the request for the model execution and determining the correct view applied to the result page. Separate scheduling logic and all view related code. If appropriate, create a public base class for all page controllers to avoid code repeat and improve consistency and testability. Figure 6 shows the relationship between the page controller and the model and view. Figure 6. Repeating code using BaseController eliminates code</p> <p>The page controller can receive a page request, extract all related data, call all updates to the model, and forward requests to the view. The view will retrieve the data to display according to the model. Defining a stand-alone page controller will separate the model to request details (such as session management, or use query strings or hidden form fields to page). Create a controller for each link in a web application in this basic form. The controller will thus become very simple because only one operation must be considered each time.</p> <p>Creating a standalone controller for each web page (or action) may result in a lot of code repeat. Therefore, the BaseController class should be created to merge the authentication parameters (see Figure 7) and other public functions. Each standalone page controller can inherit this public function from BaseController. In addition to inheriting from the public base class, you can define a set of helper classes, which can call these classes to perform public functions.</p> <p>Figure 7, separating the code depending on the web and the code that does not depend on the Web</p> <p>In most cases, the page controller depends on the specific details of the HTTP-based web request. Therefore, the page controller code typically contains references to HTTP headers, query strings, form fields, multi-port requests, etc. So test the controller code outside the web application framework. The only way is to test the controller by simulating HTTP requests and analysis results. This type of test is expensive and easy to have error. Therefore, to increase tonability, you can put the code that relies on Web's code and the code that does not depend on the web, respectively, in two separate classes, respectively (see Figure 7), which is the variant implementation of Page Controller.</p> <p>Page Controller is the default implementation of most dynamic web applications, it is simple, web application framework built-in, scalability, and its development staff's separation, etc., the advantage of making it widely used in web development, but control each page The deeper inheritance tree and the dependence on the web framework are also significantly limited.</p> <p>Highly complex optimization - FRONT Controller (front-end controller)</p> <p>The Front Controller resolves the dispersion problem exists in the Page Controller by allowing a single controller to transmit all requests. The controller itself is usually divided into two parts: handler and command hierarchy (see Figure 8).</p> <p>Figure 8, Front Controller Structure</p> <p>The handler has the following two responsibilities:</p> <p>1) Retrieve parameters. The handler receives the HTTP POST or GET request from the web server and retrieves the relevant parameters from the request.</p> <p>2) Select the command. The handler first selects the correct command in the request of the request, and then transfers the control to the command to perform processing.</p> <p>Figure 9. Typical solutions for Front Controller</p> <p>In the front-end controller, all requests are transmitted through a single (usually two parts) controllers. The first component of the controller is a handler, and the second component is a hierarchy of Commands [gof95]. The command itself is part of the controller, represents a specific operation triggered by the controller. After performing this, the command selects which view to use to render the page. Typically, the constructed this controller framework uses the configuration file to map the request to the operation, so it is easy to change after building. Of course, its disadvantage is that this design is inherently complex.</p> <p>Supplement after omissions</p> <p>So far, the implementation architecture of the MVC in the web representation has been fully demonstrated, and in this technique, the application of Page Controller and Front Controller as an optimized means for moderate complex and highly complex situations. The relatively complete solution has been given, whether the careful readers have found that is there less than? When building a web application, in addition to building a "well" system (this is currently in MVC separation and system scalable), we also need to consider the security and performance of the application, so we selected Interceptiing Filter and Page. Cache is supplemented as a web representation mode. Intercepting Filter (Filter)</p> <p>How to achieve public pre-processing and post-processing steps around the web page request? This is a problem that the filter needs to be resolved. Use this mode, you create a string combined filter to implement public pre-processing and post-processing tasks during the web page request.</p> <p>Figure 10, a string combined filter</p> <p>The filter constitutes a series of independent modules that can link together to perform a set of common processing steps before passing the page request to the controller object. Because each filter is implemented, there is no explicit dependence between each other. Therefore, new filters can be added without affecting existing filters. You can even add a filter at deployment, and the method is dynamically based on the configuration file dynamically.</p> <p>Design to individual filters should be aspected to make any assumptions for other filters as much as possible. This can maintain a combination, i.e., add, delete, or rearrange the capabilities of the filter. In addition, some frameworks that implement the IntercePting Filter mode do not guarantee the execution order of the filter. If there is a strong mutual dependency between multiple filters, it is best to take a conventional method of calling the helper class because this ensures that constraint information in the preserved filter sequence. Intercepting Filter's direct implementation is a filter chain that can be used to traverse a list consisting of all filters. The web request handler will first perform the filter chain first before passing the control to the application logic.</p> <p>Figure 11, Intercepting Filter class relationwork</p> <p>When the web server receives a page request, the request handler first passes the control to the Filterchain object. This object maintains a list containing all filters and calls each filter in order. FilterChain can read the filter sequence from the configuration file to achieve composite when deployed. Each filter has an opportunity to modify the incoming request. For example, it can modify the URL, or add the header field to be used by the application. After performing all filters, "Request Processor" passes control to the controller, the latter will execute the application function (see Figure 12).</p> <p>Figure 12, IntercePting Filter sequence diagram</p> <p>Because there is a need to intercept the filter when processing a web request, most web frameworks provide application developers to happen to the intercepting filters to the request-response process.</p> <p>Page Cache (Page Cache)</p> <p>If the dynamically generated web page is frequently requested and consumes a large number of system resources, how can we improve the response time of such a web page? The page cache is cache the content generated from the dynamic web page to improve the throughput of the request response. By default, page cache is supported in ASP.NET, but unless a valid expiration policy is defined, the output from any given response will be cached unless defined. To define an expiration policy, you can use the low-level OutputCache API or advanced @outputCache instruction.</p> <p>The basic structure of the page cache is relatively simple. The web server maintains a local data store containing the predefined page (see Figure 13). Figure 13, the basic configuration of the page cache</p> <p>The following sequence diagram illustrates the reason why the page cache can improve performance. The first sequence diagram (see Figure 2) describes the initial state of the desired page that has not been cached, that is, the so-called cache. In this case, the web server must access the database and generate an HTML page, then store it in the cache, and then return it to the client browser. Please note that this process is slower than the case where the cached is not slow, because it has performed the following additional steps:</p> <p>1. Determine if the page is cached</p> <p>2. Convert the page to HTML code and store it in the cache</p> <p>Compared to database access and HTML generation, any of the steps should not take a long time. However, because additional processing needs to be performed in this case, you must ensure that the cache is continuously hit after the system completes the steps associated with the cache, (as shown in Figure 14).</p> <p>Figure 14, cache unsatisfactory sequence (when the page is not in the cache)</p> <p>In the case of the cache hits shown in Figure 15, the page is already in the cache. By skip database access, page generation, and page storage, cache a loop.</p> <p>Figure 15, the sequence in the cache hits (when the page is in the cache)</p> <p>The following three modes can be used in ASP.NET to implement caching strategies:</p> <p>1. Insert such instruction into each page to which you want to cache. The instruction specifies the refresh interval (in seconds). Refresh interval does not rely on external events, and the cache cannot be all refreshed.</p> <p>2. Vary-by-parameter caching. This mode uses the variation of the Absolute Expiration, which enables the developer to specify parameters that affect page content. Therefore, the cache will store multiple versions of the page and prepare indexes for these page versions by parameter values.</p> <p>3. Sliding expiration caching. This mode is similar to the Absolute Expiration (absolute expiration) is that the page is valid within the specified time. However, refresh intervals are reset during each request. For example, you may use a sliding expiration cache to cache a page for up to 10 minutes. As long as the request to the page is issued within 10 minutes, the expiration time is extended for 10 minutes.</p> <p>Conclude</p> <p>Since then, we have fully introduced the Web representing the various modes related to the cluster. About the use of Observer mode in the MVC mode, we will use specialized sections, the network is your best resource. Roller (front-end controller) is complemented by MVC implementation.</p></div><div class="text-center mt-3 text-grey"> 转载请注明原文地址:https://www.9cbs.com/read-6344.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="6344" 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.052</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 = 'M3fKpvvPtIwpswYLte0IB_2FYbLvcHseSGGwaemYO1KmMkm8586CgprF_2BYHY2_2Fsl3bRrVYYp2_2BfFCDQrbGBtqAiA_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>