.Net Core MVC understand the new pipeline processing model, middleware

.Net Core middleware official website: https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.0

ASP.Net request pipeline:

 

 

   Request will eventually be processed by a specific HttpHandler (page / ashx / mvc httphandler --- action). But there are a number of steps, is packaged into an event, you can register expansion, IHttpModule, provides a very good extension.

  But there is such a flaw, it is too nosy, a http request to the core is IHttpHandler, other Cookie, Session, Session, BeginRequest, EndRequest, MapRequestHandler, authorization, does not necessarily have to have the logic of events these requests but writing was dead, they have to have, a default is considered to have some of those steps, because with the design framework concerned. .Net Framework Getting simple to master difficult, because the framework blanket, family bucket, WebForm which you can then drag a control line and the code, a project came out, so it is difficult proficient, it also pays to compare that burden re not traveling light.

ASP.Net Core:

ASP.NET Core request pipeline includes a series of requests delegate, in turn calls. The following figure illustrates this concept. The black arrow executed.

 

 

  ASP.NET Core is a new platform, is no longer backwards compatible, more the pursuit of component-based design, the pursuit of high performance, no family bucket, then ASP.NET Core is how to build a pipeline request it? By default, only a pipe 404. Then you can also increase the processing of the request, which is the former Handler, that contains only part of the business process, the other is middleware, MiddleWare.

1, Run the end of execution-style just is not going to call Next, generally as the end point. The so-called Run the end of registration, you really just an extension method, the final was not the method call Use,

app.Run(async (HttpContext context) =>
{
    await context.Response.WriteAsync("Hello World Run");
});
app.Run(async (HttpContext context) =>
{
    await context.Response.WriteAsync("Hello World Run Again");
});

2, Use means that the registration action is not an endpoint, perform next, you can perform the next middleware if you do not perform, equivalent to Run

app.Use(async (context, next) =>
{
    await context.Response.WriteAsync("Hello World Use1 <br/>");
    await next();
    await context.Response.WriteAsync("Hello World Use1 End <br/>");
});
app.Use(async (context, next) =>
{
    await context.Response.WriteAsync("Hello World Use2 Again <br/>");
    await next();
});

After may detect HttpContext UseWhen, increasing the processing chain; original normal flow of execution or

 app.UseWhen(context =>
 {
     return context.Request.Query.ContainsKey("Name");
 },
 appBuilder =>
 {
     appBuilder.Use(async (context, next) =>
     {
         await context.Response.WriteAsync("Hello World Use3 Again Again Again <br/>");
         await next();
     });
 });

app.Use (), does not call next (), that is the end point, like Run

app.Use(async (context, next) =>
{
    await context.Response.WriteAsync("Hello World Use3  Again Again <br/>");
    //await next();
});

3, Map: Specifies the middleware point endpoint depending on the conditions, there is no Next, select the branch is best not to judge the conditions in which the middleware; but a middleware only do one thing, it is more and more things children middleware

app.map ( " / the Test " , MapTest); 
app.map ( " / Bingle " , A => a.Run ( the async context => 
{ 
    the await context.Response.WriteAsync ($ " This Site Five Bingle IS " ); 
} )); 
app.MapWhen (context => 
{ 
    return context.Request.Query.ContainsKey ( " the Name " );
     // reject the request of the browser non chorme  
     // multilingual
     // the unified processing ajax 
}, MapTest);

  IApplicationBuilder application assembler, RequestDelegate: passing under a the HttpContext, asynchronous operation is not returned; i.e. a processing operation, Use (Func <RequestDelegate, RequestDelegate> middleware) delegate, passing a RequestDelegate, returns a RequestDelegate. ApplicationBuilder inside a container IList <Func <RequestDelegate, RequestDelegate >> _components, Use just go inside the container to add elements. Eventually Build () that, if there is no registered, 404 directly handle everything,

 the foreach ( var Component in _components.Reverse ()) // inverted set out for each delegate 
{ 
    App = component.Invoke (App);
     // delegate 3--404 invoked as a parameter and returns the operation of the built-in delegate 3 - as arguments to call the delegate (delegate parameter became 2) - --- cycle continues operation of the finally obtained delegate built 1 --- --- request of the HttpContext 
}

  IApplicationBuilder After the build is actually a RequestDelegate, can be addressed HttpContext, by default, the pipe is empty, is 404; according to your demands, any configured to perform everything all the freedom to customize by the developer, the framework only provides a assembly methods

In fact, the middleware can be written.

Func<RequestDelegate, RequestDelegate> middleware = next =>
{
    return new RequestDelegate(async context =>
                    {
                        await context.Response.WriteAsync("<h3>This is Middleware1 start</h3>");
                        await Task.CompletedTask;
                        await next.Invoke(context);//RequestDelegate--需要context返回Task
                        await context.Response.WriteAsync("<h3>This is Middleware1 end</h3>");
                    });
};
app.Use(middleware);

So every time trouble, to define a Func <RequestDelegate, RequestDelegate>, then go to use it? We can evolve a little bit

 app.Use(next =>
 {
     System.Diagnostics.Debug.WriteLine("this is Middleware1");
     return new RequestDelegate(async context =>
     {
         await context.Response.WriteAsync("<h3>This is Middleware1 start</h3>");
         await next.Invoke(context);
         await context.Response.WriteAsync("<h3>This is Middleware1 end</h3>");
     });
 });

 app.Use(next =>
 {
     System.Diagnostics.Debug.WriteLine("this is Middleware2");
     return new RequestDelegate(async context =>
     {
         await context.Response.WriteAsync("<h3>This is Middleware2 start</h3>");
         await next.Invoke(context);
         await context.Response.WriteAsync("<h3>This is Middleware2 end</h3>");
     });
 });
 app.Use(next =>
 {
     System.Diagnostics.Debug.WriteLine("this is Middleware3");
     return new RequestDelegate(async context =>
     {
         await context.Response.WriteAsync("<h3>This is Middleware3 start</h3>");
         //await next.Invoke(context);//注释掉,表示不再往下走
         await context.Response.WriteAsync("<h3>This is Middleware3 end</h3>");
     });
 });

As a result, the order of execution is as follows:

<h3>This is Middleware1 start</h3>
<h3>This is Middleware2 start</h3>
<h3>This is Middleware3 start</h3>

<h3>This is Middleware3 end</h3>
<h3>This is Middleware2 end</h3>
<h3>This is Middleware1 end</h3>

ActionFilter is not like before, is a Russian doll, I prefer to say that the onion model. In fact, because the source code, the IList <Func <RequestDelegate, RequestDelegate >> _components, the _components.Reverse () the collection reversed.

That middleware code, following such an approach is not good?

 app.Use(async (context, next) =>
 {
     //Do work that doesn't write to the Response
     await next.Invoke();
     //Do logging or other work that doesn't write to the Response
 });

 app.Run(async context =>
 {
     await context.Response.WriteAsync("Hello from 2nd delegate.");
 });

ApplicationBuilder inside a container IList <Func <RequestDelegate, RequestDelegate >> _components. Use only when he went inside the container to add elements, eventually Build () that, if there is no registered, 404 directly handle everything.

 

 3 404 --- commissioned as calling, returns a delegate 3 built as an operation parameter to call --- delegate (delegate parameter became 2) --- cycle continues, eventually built to obtain the operation of a delegate, the request HttpContext , IApplicationBuilder, after the build is actually a RequestDelegate, can be addressed HttpContext, by default, the pipe is empty, that is 404, according to your demands, any configured to perform, all that developers the freedom to customize the frame only to provide an assembly method.

Middleware which can be encapsulated into a logical category to:

 public class FirstMiddleWare
 {
     private readonly RequestDelegate _next;

     public FirstMiddleWare(RequestDelegate next)
     {
         this._next = next;
     }


     public async Task Invoke(HttpContext context)
     {
         await context.Response.WriteAsync($"{nameof(FirstMiddleWare)},Hello World1!<br/>");

         await _next(context);

         await context.Response.WriteAsync($"{nameof(FirstMiddleWare)},Hello World2!<br/>");
     }

 }

When in use:

app.UseMiddleware<FirstMiddleWare>();

In fact, we can upgrade a little bit, use extension methods, this class as a logical extension of the method IApplicationBuilder.

public static class MiddleExtend
{
    public static IApplicationBuilder UseFirstMiddleWare(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<FirstMiddleWare>();
    }
}

When using the much simpler

app.UseFirstMiddleWare();

 

Guess you like

Origin www.cnblogs.com/taotaozhuanyong/p/11600770.html