ASP. NET Core3.X Terminal Middleware Transforming to Endpoint Routing Running Detailed Explanation

  • 2021-11-13 01:16:12
  • OfStack

Introduction

A few days ago, NET Core3.1 was released, so I upgraded a basic general system of the company and deleted several basic modules. Of course, these basic modules have nothing to do with NET Core3.1, including the payment module. After the upgrade, Jing Wen (colleague) asked me that you deleted the payment. I said yes, I didn't think about how to add it (I don't feel very good at present, I need to redesign it for 1 time).

The story begins here

When considering payment, I think about how to introduce payment sdk directly into the system, and how to have a series of payment routes. What I need to consider is if I create a response to the specified address, so. I began to think about how to achieve my goal of customizing a middleware, Use, Run, Map. ? ?

Advanced routing

Routing is responsible for mapping request URI to endpoints and scheduling incoming requests to those endpoints. Routing is defined in the application and configured when the application starts. The route can optionally extract values from the URL contained in the request, which can then be used to process the request. Routing can also generate an URL mapped to an endpoint by using routing information in the application.

In ASP. NET Core 2.1 and earlier, routing is handled by implementing an interface that maps URL incoming from IRouter to a handler. Typically, a direct reliance on MvcMiddleware is added to the implementation at the end of the middleware pipeline, rather than directly implementing the interface. 1 Once the request arrives at MvcMiddleware, routing is applied to determine the controller and operation corresponding to the incoming request URL path.

The request then passes through various MVC filters before executing the handler. These filters form another "pipeline," reminiscent of the middleware pipeline, and in some cases must replicate the behavior of certain middleware. A typical example is CORS policy. In order to implement a different CORS policy for each MVC operation and other "branches" of the middleware pipeline, a certain degree of duplication is required internally.

"Branching" middleware pipes are commonly used for "pseudo-routing." Extension methods such as Map () in the middleware pipeline will allow you to conditionally execute certain middleware when the incoming path has a given prefix.

As shown below:


  app.Map("/order", app => app.Run(async context =>
    {
     await context.Response.WriteAsync("Order");
    })
   );

In this case, the Run () method is a "terminal" middleware because it returns a response. But in a sense, the entire Map branch corresponds to the "endpoint" of the application.

In ASP. NET Core 2.2, endpoint routing is introduced as a new routing mechanism for MVC controllers. This implementation is essentially an internal implementation of MvcMiddleware.

Use Map () in ASP. NET Core 2. x

Let's customize a middleware, which returns a corresponding one directly instead of continuing to execute the call _ next delegate, a very basic middleware.


 public class ApiEndpointMiddleware
 {
  private readonly RequestDelegate _next;

  public ApiEndpointMiddleware(RequestDelegate next)
  {
   _next = next;
  }

  public async Task InvokeAsync(HttpContext context)
  {
   
   context.Response.StatusCode = 200;

   await context.Response.WriteAsync("Order");
  }

 }

In ASP. NET Core 2. x, you can include the middleware in the middleware pipeline of Startup. cs by specifying a route to access the middleware using an extension method


public void Configure(IApplicationBuilder app)
{
 app.UseStaticFiles();

 app.Map("/order", app => app.UseMiddleware<ApiEndpointMiddleware>()); versionApp.UseMiddleware<VersionMiddleware>()); 

 app.UseMvcWithDefaultRoute();
}

When we access the/order or/order/1 route, we get the corresponding return from the custom middleware.

Converting middleware to endpoint routing

In ASP. NET Core 3.0, we use endpoint routing, so the routing step is separate from the call to the endpoint. In fact, this means that we have two middleware:

The actual route of the EndpointRoutingMiddleware, which calculates which endpoint will be invoked for the specified requested URL path. EndpointMiddleware the endpoint of all calls.

They are added at two different points in the middleware pipeline because they serve two different roles. 1 In general, we want to route the middleware ahead of time in the pipeline so that subsequent middleware can access information about the endpoints that will be executed. The call to the endpoint should be made at the end of the pipeline.

As shown below:


public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  {
   if (env.IsDevelopment())
   {
    app.UseDeveloperExceptionPage();
   }

   app.UseHttpsRedirection();

   app.UseRouting();

   app.UseAuthorization();

   app.UseEndpoints(endpoints =>
   {
    endpoints.MapControllers();
   });

  }

The UseRouting () extension method adds EndpointRoutingMiddleware to the pipeline, while the UseEndpoints () extension method adds EndpointMiddleware to the pipeline. UseEndpoints () actually registers the locations of all endpoints for the application.

So how do we map our custom middleware using endpoint routing?

Conceptually, our UseEndpoints () uses/OrderURL as the matching path to move the registration of the "order" endpoint into the call:


  endpoints.MapControllers();
    endpoints.Map("/order",endpoints.CreateApplicationBuilder()
    .UseMiddleware<ApiEndpointMiddleware>().Build()).WithDisplayName("order-api");

In our previous implementation for ASP. NET Core 2. x, we will match endpoint routes such as/order,/order/123

For example:


endpoints.Map("/order/{action}",null);

This will match the/order/order/1 at the same time, but not the/order/status/1. It is much more powerful than previous versions.

In the previous example, we provided a display name (primarily for debugging purposes), but we could attach additional information, such as authorization policies or CORS policies, that other middleware could query. For example:


  app.UseEndpoints(endpoints =>
   {
    endpoints.MapControllers();
    endpoints.Map("/order/{action}",endpoints.CreateApplicationBuilder()
    .UseMiddleware<ApiEndpointMiddleware>().Build()).WithDisplayName("order-api").RequireCors("AllowAllHosts")
   .RequireAuthorization("AdminOnly"); 
   });

We added an CORS policy (AllowAllHosts) and an authorization policy (AdminOnly) to the endpoint. When the request arriving at the endpoint arrives, take corresponding measures before executing the endpoint.

Reference

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-3.1#endpoint-routing-differences-from-earlier-versions-of-routing


Related articles: