Asp.net core mvc implements pseudo-static functions, coremvc

Source: Internet
Author: User

Asp.net core mvc implements pseudo-static functions, coremvc

In large website systems, to improve system access performance, some infrequently changed content is often published as static pages, such as the product details page and news details page of the mall, once the information is published, the change frequency will not be very high. If dynamic output is used for processing, it will definitely cause a great waste of resources on the server. However, we cannot independently create static pages for these contents. Therefore, we can use pseudo-static methods in the system for processing. For what is pseudo-static, you can use Baidu. Here we will introduce how to implement pseudo-static in asp.net core mvc.

In the mvc Framework, view represents a view. The result of its execution is the content that is finally output to the client browser, including html, css, and js. If we want to achieve static state, we need to save the view execution result as a static file and save it to the specified location, such as disk and distributed cache, you can directly read the saved content next time without executing the business logic. So what should asp.net core mvc do to implement such a function? The answer is to use filters. In the mvc Framework, multiple filter types are provided. Here we want to use the action filter, which provides two time points: before the action is executed, after the action is executed. Before executing an action, we can determine whether a static page has been generated. If a static page has been generated, we can directly read the file content and output it. The subsequent logic will be skipped. If there is no production, proceed to the next step, capture the results at this stage after the action is executed, and save the static content generated by the results.

Then let's get the specific implementation code. First we define a filter type and we will become StaticFileHandlerFilterAttribute. This class is derived from the ActionFilterAttribute and StaticFileHandlerFilterAttribute provided by the Framework to override the two methods provided by the base class: onActionExecuted (after the action is executed) and OnActionExecuting (before the action is executed). The Code is as follows:

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method, AllowMultiple = false, Inherited = false)]public class StaticFileHandlerFilterAttribute : ActionFilterAttribute{   public override void OnActionExecuted(ActionExecutedContext context){}   public override void OnActionExecuting(ActionExecutingContext context){}}

In OnActionExecuting, You need to determine whether the static content has been generated. If the content has been directly output, the logic implementation is as follows:

// Generate the static file name according to certain rules. Here, the string controllerName = context is generated according to the area + "-" + controller + "-" + action + key rule. routeData. values ["controller"]. toString (). toLower (); string actionName = context. routeData. values ["action"]. toString (). toLower (); string area = context. routeData. values ["area"]. toString (). toLower (); // The Key here is equal to id by default. Of course, we can configure different Key names string id = context. routeData. values. containsKey (Key )? Context. routeData. values [Key]. toString (): ""; if (string. isNullOrEmpty (id) & context. httpContext. request. query. containsKey (Key) {id = context. httpContext. request. query [Key];} string filePath = Path. combine (AppContext. baseDirectory, "wwwroot", area, controllerName + "-" + actionName + (string. isNullOrEmpty (id )? "": ("-" + Id) + ". html "); // determine whether the object exists if (File. exists (filePath) {// If yes, directly read the File using (FileStream fs = File. open (filePath, FileMode. open) {using (StreamReader sr = new StreamReader (fs, Encoding. UTF8) {// use contentresult to return the file content ContentResult contentresult = new ContentResult (); contentresult. content = sr. readToEnd (); contentresult. contentType = "text/html"; context. result = contentresult ;}}}

In OnActionExecuted, we need the result action result to determine whether the action result type is a ViewResult. If the result is executed by code, the result output is obtained and a static page is generated according to the same rule as above, the specific implementation is as follows:

// Obtain the result IActionResult actionResult = context. result; // determine whether the Result is a ViewResult if (actionResult is ViewResult) {ViewResult viewResult = actionResult as ViewResult; // the following code executes this ViewResult, put the html content of the result into a StringBuiler object. var services = context. httpContext. requestServices; var executor = services. getRequiredService <ViewResultExecutor> (); var option = services. getRequiredService <IOptions <MvcViewOptions> (); Var result = executor. findView (context, viewResult); result. ensureSuccessful (originalLocations: null); var view = result. view; StringBuilder builder = new StringBuilder (); using (var writer = new StringWriter (builder) {var viewContext = new ViewContext (context, view, viewResult. viewData, viewResult. tempData, writer, option. value. htmlHelperOptions); view. renderAsync (viewContext ). getAwaiter (). ge TResult (); // This sentence must be called, otherwise the content will be empty writer. flush ();} // generate the static file name string area = context according to the rule. routeData. values ["area"]. toString (). toLower (); string controllerName = context. routeData. values ["controller"]. toString (). toLower (); string actionName = context. routeData. values ["action"]. toString (). toLower (); string id = context. routeData. values. containsKey (Key )? Context. routeData. values [Key]. toString (): ""; if (string. isNullOrEmpty (id) & context. httpContext. request. query. containsKey (Key) {id = context. httpContext. request. query [Key];} string devicedir = Path. combine (AppContext. baseDirectory, "wwwroot", area); if (! Directory. exists (devicedir) {Directory. createDirectory (devicedir);} // Write File string filePath = Path. combine (AppContext. baseDirectory, "wwwroot", area, controllerName + "-" + actionName + (string. isNullOrEmpty (id )? "": ("-" + Id) + ". html "); using (FileStream fs = File. open (filePath, FileMode. create) {using (StreamWriter sw = new StreamWriter (fs, Encoding. UTF8) {sw. write (builder. toString () ;}}// output the current result ContentResult contentresult = new ContentResult (); contentresult. content = builder. toString (); contentresult. contentType = "text/html"; context. result = contentresult ;}

For the Key mentioned above, we directly add the corresponding attribute

public string Key{  get;set;}

In this way, we can use this filter. The [StaticFileHandlerFilter] feature is added to the Controller or controller method. If you want to configure different keys, you can use [StaticFileHandlerFilter (Key = "Set Value")]

Static has been implemented. We also need to consider the update. If an article is updated in the background, we have to update the static page as well. There are many solutions: one is to delete the corresponding static page synchronously when the content is updated in the background. We will introduce another method, regular update, that is, to enable the static page to have a certain validity period, which is automatically updated after this validity period. To implement this logic, we need to obtain the creation time of the static page in the OnActionExecuting method, and then compare it with the current time to determine whether the page has expired. If the page has not expired, the page is output directly. If the page has expired, continue to execute the following logic. The Code is as follows:

// FileInfo fileInfo = new FileInfo (filePath), object for obtaining file information; // settlement interval. If it is less than or equal to two minutes, it is output directly, of course, the rule here can be changed to TimeSpan ts = DateTime. now-fileInfo. creationTime; if (ts. totalMinutes <= 2) {using (FileStream fs = File. open (filePath, FileMode. open) {using (StreamReader sr = new StreamReader (fs, Encoding. UTF8) {ContentResult contentresult = new ContentResult (); contentresult. content = sr. readToEnd (); contentresult. contentType = "text/html"; context. result = contentresult ;}}}

By now, the pseudo-static state can be implemented. The current processing method can only improve the access performance to a certain extent, but it may not be enough for large portal systems. According to the method described above, other functions can be expanded. For example, static pages can be generated and published to CDN, or to a separate content server. Regardless of the method, the implementation idea is the same.

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

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.