【问题标题】:Middleware breaks the web api calls中间件中断 web api 调用
【发布时间】:2019-11-05 09:09:56
【问题描述】:

我有一个中间件来记录 web api 请求。下面是Startup.cs 中的Configuration 方法。如果app.UseMiddleware 出现在app.UseMvc 之前,则不会调用任何Web api 调用但是,如果app.UseMiddleware 出现在app.UseMvc 之后,则中间件不会执行任何操作(即记录请求)。

我提供了下面的代码。任何想法为什么app.UseMiddleware 会干扰asp.UseMvc

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider services)
{
    // global cors policy
    app.UseCors(x => x
        .AllowAnyOrigin()
        .AllowAnyMethod()
        .AllowAnyHeader());


    app.UseHttpsRedirection();
    app.UseAuthentication();

    app.UseStaticFiles();
    app.UseSpaStaticFiles();

    app.UseMiddleware<ApiLoggingMiddleware>();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller}/{action=Index}/{id?}");
    });
}

下面是中间件:

 public async Task Invoke(HttpContext httpContext, IApiLogService apiLogService)
 {
     try
     {
         _apiLogService = apiLogService;

         var request = httpContext.Request;
         if (request.Path.StartsWithSegments(new PathString("/api")))
         {
             var stopWatch = Stopwatch.StartNew();
             var requestTime = DateTime.UtcNow;
             var requestBodyContent = await ReadRequestBody(request);
             var originalBodyStream = httpContext.Response.Body;

             await SafeLog(requestTime,
                   stopWatch.ElapsedMilliseconds,
                   200,//response.StatusCode,
                   request.Method,
                   request.Path,
                   request.QueryString.ToString(),
                   requestBodyContent
                   );           
         }
         else
         {
             await _next(httpContext);
         }
     }
     catch (Exception ex)
     {
         await _next(httpContext);
     }
 }

【问题讨论】:

  • 能否请您分享更多中间件代码,因为在上面的代码中,我发现缺少的部分是 requestdelegate more info here 也可以查看 this
  • @Miky 感谢您的评论。通过将await _next(httpContext); 放在else 之外,问题就解决了

标签: c# asp.net asp.net-web-api middleware


【解决方案1】:

您必须始终在中间件中调用await _next(httpContext);,否则请求不会进入管道:

public async Task Invoke(HttpContext httpContext, IApiLogService apiLogService)
 {
     try
     {
         _apiLogService = apiLogService;

         var request = httpContext.Request;
         if (request.Path.StartsWithSegments(new PathString("/api")))
         {
             var stopWatch = Stopwatch.StartNew();
             var requestTime = DateTime.UtcNow;
             var requestBodyContent = await ReadRequestBody(request);
             var originalBodyStream = httpContext.Response.Body;

             await SafeLog(requestTime,
                   stopWatch.ElapsedMilliseconds,
                   200,//response.StatusCode,
                   request.Method,
                   request.Path,
                   request.QueryString.ToString(),
                   requestBodyContent
                   );           
         };
     }
     catch (Exception ex)
     {

     }
     await _next(httpContext);
 }

编辑(中间件简单说明):
整个中间件的工作方式如下:当请求到达您的应用程序时,它通过中间件管道,每个中间件必须调用下一个中间件才能最终将请求发送到您的控制器。当您调用 await _next(httpContext); 时,您基本上是在调用管道中下一个中间件的 Invoke 方法。如果您不致电await _next(httpContext);,您将停止请求并且它不会到达您的控制器。需要注意的一点是,当await _next(httpContext); 返回时,您的控制器已经处理了请求。

【讨论】:

  • 感谢您的回答。你的意思是它不应该在else里面?
  • 我在答案中添加了中间件的简单解释,更多信息请查看microsoft documentation
猜你喜欢
  • 1970-01-01
  • 2023-03-20
  • 2019-01-08
  • 2019-07-12
  • 2022-11-22
  • 1970-01-01
  • 2013-10-01
  • 1970-01-01
  • 2020-10-02
相关资源
最近更新 更多