Run 方法

Run 方法源码:

  1. /// <summary>
  2. /// Adds a terminal middleware delegate to the application's request pipeline.
  3. /// </summary>
  4. /// <param name="app">The <see cref="T:Microsoft.AspNetCore.Builder.IApplicationBuilder" /> instance.</param>
  5. /// <param name="handler">A delegate that handles the request.</param>
  6. public static void Run(this IApplicationBuilder app, RequestDelegate handler)
  7. {
  8. if (app == null)
  9. throw new ArgumentNullException(nameof (app));
  10. if (handler == null)
  11. throw new ArgumentNullException(nameof (handler));
  12. app.Use((Func<RequestDelegate, RequestDelegate>) (_ => handler));
  13. }

不难看出 Run 方法就是专门用来添加 terminal middleware(终端中间件)的。

一个管道中通常只有一个终端中间件。

Use 方法

Use 源码:

  1. /// <summary>
  2. /// Adds a middleware delegate defined in-line to the application's request pipeline.
  3. /// </summary>
  4. /// <param name="app">The <see cref="T:Microsoft.AspNetCore.Builder.IApplicationBuilder" /> instance.</param>
  5. /// <param name="middleware">A function that handles the request or calls the given next function.</param>
  6. /// <returns>The <see cref="T:Microsoft.AspNetCore.Builder.IApplicationBuilder" /> instance.</returns>
  7. public static IApplicationBuilder Use(
  8. this IApplicationBuilder app,
  9. Func<HttpContext, Func<Task>, Task> middleware)
  10. {
  11. return app.Use((Func<RequestDelegate, RequestDelegate>) (next => (RequestDelegate) (context =>
  12. {
  13. Func<Task> func = (Func<Task>) (() => next(context));
  14. return middleware(context, func);
  15. })));
  16. }

Use 用于在管道中添加 in-line(内联定义的)中间件。

请求管道

  1. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  2. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILogger<Startup> logger)
  3. {
  4. if (env.IsDevelopment())
  5. {
  6. app.UseDeveloperExceptionPage();
  7. }
  8. app.Use(async (context, next) =>
  9. {
  10. context.Response.ContentType = "text/plain;charset=utf-8";
  11. logger.LogInformation("MW1: 传入请求");
  12. await next();
  13. logger.LogInformation("MW1: 传出响应");
  14. });
  15. app.Use(async (context, next) =>
  16. {
  17. logger.LogInformation("MW2: 传入请求");
  18. await next();
  19. logger.LogInformation("MW2: 传出响应");
  20. });
  21. app.Run(async (context) =>
  22. {
  23. logger.LogInformation("MW3: 传入请求");
  24. await context.Response.WriteAsync("MW3:处理请求,并生成响应");
  25. logger.LogInformation("MW3: 传出响应");
  26. });
  27. }

输出:

  1. Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:3290/
  2. StudentManagement.Startup:Information: MW1: 传入请求
  3. StudentManagement.Startup:Information: MW2: 传入请求
  4. StudentManagement.Startup:Information: MW3: 传入请求
  5. StudentManagement.Startup:Information: MW3: 传出响应
  6. StudentManagement.Startup:Information: MW2: 传出响应
  7. StudentManagement.Startup:Information: MW1: 传出响应
  8. Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 29.7525ms 200 text/plain;charset=utf-8

配置 ASP.NET Core 请求处理管道 - 图1

  • 所有的请求处理都会在每个中间件组件调用 next() 方法之前触发。请求按照途中箭头所示,依次穿过所有管道
  • 当(终端)中间件处理请求并产生响应时,请求流程会在管道开始反向传递