ASP. NET Core Webapi study notes (iv)--middleware
The first part: Pipeline Model 1. ASP. NET Pipeline
In the previous ASP. NET, the main pipeline model flow is as follows:
After the request enters the ASP. NET worker process, the process creates the Httpworkrequest object, encapsulates all the information about the request, and then enters the HttpRuntime class for further processing. HttpRuntime creates a HttpContext context object from the request information, which runs through the pipeline until the response ends. Creates or initializes a HttpApplication object from the application pool, which begins processing multiple httpmodule that were previously registered. The handlerfactory is then called to create the handler handler, which eventually processes the request content and generates a response return.
A simple ASP. NET program is used to verify this process.
Use VS2015 to create an empty ASP. Add HttpModule.cs, HttpHandler.cs, Global.asax files according to the wizard
Configure Web. config. The following are the configuration contents in the IIS7 environment.
1 <?xml version= "1.0" encoding= "Utf-8"?> 2 <!--3 For more information about how to configure an ASP. NET application, go to 4 http://go.microsoft.co m/fwlink/? linkid=169433 5--6 <configuration> 7 <system.web> 8 <compilation debug= "true" targetframework = "4.5"/> 9
Start debugging, access the address Http://localhost:5383/index.handler, you can see the page content.
The previous version of ASP. NET MVC was extended by the UrlRoutingModule.cs class and the MvcHandler.cs class to implement the MVC framework.
2. ASP. NET Core PipelineIn the ASP. NET core, the pipeline model process has changed a lot:
IHttpModule and IHttpHandler no longer exist and are replaced by middleware (middleware).
The server passes the received request directly backward, sequentially through each middleware processing, then by the last middleware processing and generating the response content after the callback, and then reverse sequentially through each middleware, until the server sent out.
Middleware is like a layer of "filter", filtering all requests and corresponding. This design works well for scenarios such as request-response, where messages flow from the pipe head to the last reverse flow.
The next step is to demonstrate how middleware functions are implemented in ASP.
Part II, middlewareIn fact, in the first part of the series, a simple usage of the pipeline has been shown. Here is a detailed explanation of how to implement a custom pipeline.
Middleware supports run, use, and map three methods for registering, and the following shows how each method is used.
First, the Run methodAll custom pipelines that need to be implemented are added to the Startup.cs Configure method.
1 public void Configure (Iapplicationbuilder app, Iloggerfactory loggerfactory) 2 {3 //Add log support 4 Loggerfactory.addconsole (); 5 Loggerfactory.adddebug (); 6 7 //Add Nlog Log support 8 loggerfactory.addnlog (); 9 //Add custom Middleware 11 app. Run (Async context =>12 { await context). Response.writeasync ("Hello world!"); +/ /Add MVC middleware //app. Usemvc ();
Start debugging, Access address http://localhost:5000/, page display Hello world! Words.
Add a Run method again
1 public void Configure (Iapplicationbuilder app, Iloggerfactory loggerfactory) 2 {3 //Add log support 4 Loggerfactory.addconsole (); 5 Loggerfactory.adddebug (); 6 7 //Add Nlog Log support 8 loggerfactory.addnlog (); 9 //Add custom Middleware 11 app. Run (Async context =>12 { await context). Response.writeasync ("Hello world!"); ), and the app. Run (Async context =>17 {) await context. Response.writeasync ("Hello World Too!"); +/ /Add MVC middleware //app. Usemvc ();
Start debugging and revisit the discovery page with only the word Hello world!.
The reason for this is that this usage of run means that the registered middleware is the last middleware in the pipeline, which is returned directly after processing the request.
Second, use method1 public void Configure (Iapplicationbuilder app, Iloggerfactory loggerfactory) 2 {3 //Add log support 4 Loggerfactory.addconsole (); 5 Loggerfactory.adddebug (); 6 7 //Add Nlog Log support 8 loggerfactory.addnlog (); 9 //Add custom Middleware 11 app. Use (Async (context, next) =>12 { await context. Response.writeasync ("Hello world!"); +/ /Add MVC middleware //app. Usemvc ();
Start debugging, the Access page also displays the word Hello world!. We found that using the use method instead of the Run method allows the same functionality.
Once again add a use method, the original usage method to adjust the content slightly, try to implement the page display two Hello world! words.
1 public void Configure (Iapplicationbuilder app, Iloggerfactory loggerfactory) 2 {3 //Add log support 4 Loggerfactory.addconsole (); 5 Loggerfactory.adddebug (); 6 7 //Add Nlog Log support 8 loggerfactory.addnlog (); 9 //Add custom middleware one by one App. Use (Async (context, next) =>12 { await context. Response.writeasync ("Hello world!"); next (), and the app. Use (Async (context, next) =>18 { await context. Response.writeasync ("Hello World Too!"); +/ /Add MVC middleware to //app. Usemvc ();
Start debugging, access the page
Change the two use methods in order, slightly adjust the content, start debugging again, access the page, and found that the output order of the typeface also changed.
1 public void Configure (Iapplicationbuilder app, Iloggerfactory loggerfactory) 2 {3 //Add log support 4 Loggerfactory.addconsole (); 5 Loggerfactory.adddebug (); 6 7 //Add Nlog Log support 8 loggerfactory.addnlog (); HelloworldMiddleware.cs 9 //Add custom middleware one-to -one app. Use (Async (context, next) =>12 { await context. Response.writeasync ("Hello World Too!"); next (), and the app. Use (Async (context, next) =>18 { await context. Response.writeasync ("Hello world!"); +/ /Add MVC middleware to //app. Usemvc ();
As you can see from the example above, the middleware registered with the use method is equivalent to the Run method if the next method is not called. When the next method is called, the middleware will pass the request and continue processing by the subsequent middleware.
When registering the middleware order is different, the order of processing is not the same, it is very important, when the number of registered custom middleware, you need to consider which middleware first processing requests, which middleware post-processing requests.
In addition, we can write the middleware separately as a separate class, through the Usemiddleware method can also complete the registration. The demo functionality above will be rewritten with a separate middleware class.
New two middleware classes: HelloworldMiddleware.cs, HelloworldTooMiddleware.cs
HelloworldMiddleware.csHelloworldTooMiddleware.csModify The contents of the Configure method for Startup.cs
1 public void Configure (Iapplicationbuilder app, Iloggerfactory loggerfactory) 2 {3 //Add log support 4 Loggerfactory.addconsole (); 5 Loggerfactory.adddebug (); 6 7 //Add Nlog Log support 8 loggerfactory.addnlog (); 9 //Add custom middleware one by one App. Usemiddleware
Start debugging, access the page, you can see the same effect.
Third, map methodThe map method primarily specifies the registered middleware through the request path and other custom conditional filters, and looks more like a route.
Modify The contents of the Configure method of Startup.cs and add static methods Maptest
1 public void Configure (Iapplicationbuilder app, Iloggerfactory loggerfactory) 2 {3 //Add log support 4 Loggerfactory.addconsole (); 5 Loggerfactory.adddebug (); 6 7 //Add Nlog Log support 8 loggerfactory.addnlog (); 9 //Add custom middleware one by one App. Map ("/test", maptest); //Add MVC middleware //app. Usemvc (); }16- private static void Maptest (Iapplicationbuilder app) { app. Run (Async context = {) await context. Response.writeasync ("URL is" + context.) Request.PathBase.ToString ());
Start debugging, access the path http://localhost:5000/test, the page displays the following content
However, when accessing other paths, the page does not display content. From this you can see that the map method uses a similar routing mechanism to direct specific URL address requests into a fixed method, which is handled by a particular middleware.
In addition, the map method can also implement multi-level URL "route", in fact, the map method is nested use
1 //Add custom middleware 2 app. Map ("/level1", Lv1app + = {3 app). Map ("/level1.1", Lv11app = {4 ///level1/level1.1 5 6 }); 7 8 app. Map ("/level1.2", Lv12app = {9 ///level1/level1.210 });
You can also use the Mapwhen method to "route" using a custom condition
1 public void Configure (Iapplicationbuilder app, Iloggerfactory loggerfactory) 2 {3 //Add log support 4 Loggerfactory.addconsole (); 5 Loggerfactory.adddebug (); 6 7 //Add Nlog Log support 8 loggerfactory.addnlog (); 9 //Add custom middleware one by one App. Mapwhen (Context =>12 { return context. Request.Query.ContainsKey ("a"); maptest); add MVC middleware //app. Usemvc (), }19 the private static void Maptest (Iapplicationbuilder app) (app) . Run (Async context =>23 { await context). Response.writeasync ($ "URL is {context. Request.Path.ToString ()}{context. Request.QueryString.Value} ");
Start debugging, access the path http://localhost:5000/path?a=1&b=2, the page displays the following content
The page will display content only if the request parameter contains a.
Iv. other built-in middlewareSeveral middleware built into the ASP.
Finally, a simple access logging function is implemented with custom middleware to record the content and response time of each request.
1. Add a log model VisitLog.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 5 Namespace Webapiframe.models 6 {7 public class Visitlog 8 {9 public string Url {get; set;} Ten public idictionary<string, string> Headers {get; set;} = new dictionary<string, string> (); 12 1 3 public string Method {get; set;} public string Requestbody {get; set;} Excutestarttime public DateTime {get; set;} Public DateTime excuteendtime {get; set;} public override string ToString (), {string headers = "[" + String. Join (",", this. Headers.select (i + = "{" + $ "\" {i.key}\ ": \" {i.value}\ "" + "}")) + "]"; "Return $" URL: {this. Url},\r\nheaders: {headers},\r\nmethod: {this. Method},\r\nrequestbody: {this. Requestbody},\r\nexcutestarttime: {this. Excutestarttime.tostring ("Yyyy-mm-dd HH:mm:ss.fff")},\r\nexcutestarttime: {this. Excuteendtime.tostring ("Yyyy-mm-dd HH:mm:ss.fff")} "; 25}26}27}
2. Add the Access logging middleware VisitLogMiddleware.cs, and add the Usevisitlogger extension method.
1 using Microsoft.AspNetCore.Builder; 2 using Microsoft.AspNetCore.Http; 3 using Microsoft.Extensions.Logging; 4 using System; 5 using System.IO; 6 using System.Linq; 7 using System.Threading.Tasks; 8 using Webapiframe.models; 9 namespace WebApiFrame.Core.Middlewares11 {public class VisitLogMiddleware13 {readonly R Equestdelegate _next;15 readonly ILogger logger;17 private Visitlog visitlog;19 p Ublic Visitlogmiddleware (requestdelegate Next, Iloggerfactory loggerfactory) {_next = next;23 Logger = loggerfactory.createlogger<visitlogmiddleware> ();}25 public async Task Invok E (HttpContext context) {Visitlog = new Visitlog (); HttpRequest request = context. request;30 Visitlog.url = Request. Path.tostring (); visitlog.headers = Request. Headers.todictionary (k = K.key, v = = string. Join (";", V.value.tolist ())); Visitlog.method = Request. method;33 visitlog.excutestarttime = datetime.now;34 using (StreamReader reader = new Streamrea Der (Request. Body) (visitlog.requestbody) = reader. ReadToEnd ();}39. Response.oncompleted (responsecompletedcallback, context); _next await (context);}43 Vate Task responsecompletedcallback (Object obj) {visitlog.excuteendtime = datetime.now;47 Logger. Loginformation ($ "Visitlog: {visitlog.tostring ()}"); return Task.fromresult (0); 49}50}51 52 public static class VisitLogMiddlewareExtensions53 {iapplicationbuilder-public static-Usevisitlogger (this I Applicationbuilder builder). Usemiddleware<visitlogmiddleware> (); 57}58}59}
3. adding middleware support in Startup.cs
1 public void Configure (Iapplicationbuilder app, Iloggerfactory loggerfactory) 2 {3 //Add log support 4 Loggerfactory.addconsole (); 5 Loggerfactory.adddebug (); 6 7 //Add Nlog Log support 8 loggerfactory.addnlog (); 9 //Add custom Middleware 11 app. Usevisitlogger (); app. Run (Async context =>14 { await context). Response.writeasync ("Hello world!"); +/ /Add MVC middleware //app. Usemvc ();
4. Start debugging, Access address http://localhost:5000/, and view the debug console log printing information.
In addition, if you are more careful you will find that in the Configure method has such a code: the app. Usemvc (); , ASP. NET Core MVC is the way to borrow middleware to extend the implementation of the MVC framework.
Category: ASP. NET CoreASP. NET Core Webapi study notes (iv)--middleware