为什么 ASP.NET Core 只执行一次自定义中间件?

Why is ASP.NET Core executing a custom middleware only once?

我有一个 ASP.NET 核心,其控制器接受 POST 请求:

[Route("api/v1/tenants/tests")]
public class TestsController : Controller
{
    [HttpPost]       
    public IActionResult Post(string tenantId)
    {
        return Ok();
    }
}

我开发了一个 'null' 中间件来测试。它在 Startup.cs 文件的 Configure 方法中定义:

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

     app.UseMvc();

     app.Use(async (context, next) =>
     {
         // Forward to the next one.
         await next.Invoke();
     });
}

问题

当我通过 Postman 调用控制器时,对 POST 方法的初始调用成功通过中间件,然后到达控制器。但是,以下调用直接转到控制器,完全跳过中间件。这是为什么?

Startup.Configure() 在应用程序启动期间执行一次。它用于为应用程序做准备,它不会在每次调用时执行。但是,您可以使用它来设置每次调用都会执行的中间件。 microsoft documentation for asp.net core application startup 包含一些示例 ConfigureConfigureServices

中间件必须在调用app.UseMvc()之前设置。

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

     app.Use(async (context, next) =>
     {
         // Forward to the next one.
         await next.Invoke();
     });

     // !! Have to be called after setting up middleware !!
     app.UseMvc();
}

此信息存在于 documentation 中,但我不知道它也适用于自定义中间件:

The order that middleware components are added in the Startup.Configure method defines the order in which the middleware components are invoked on requests and the reverse order for the response. The order is critical for security, performance, and functionality.

The following Startup.Configure method adds middleware components for common app scenarios:

1 - Exception/error handling

2 - HTTP Strict Transport Security Protocol

3 - HTTPS redirection

4 - Static file server

5 - Cookie policy enforcement

6 - Authentication

7 - Session

8 - MVC

更新

在ASP.NetCore 3.0中,你需要在MapControllers()

之前添加你的中间件
 app.UseEndpoints(endpoints =>
 {
     endpoints.MapControllers();
 });