首页 > 解决方案 > 在.net core 2 web api中添加日志中间件,导致http 307和400错误响应

问题描述

我想使用 aspnet core sample 提供的日志中间件。在我添加日志中间件之前,一切正常。添加日志中间件后,我收到错误消息。

添加中间件之前:

info: Microsoft.AspNetCore.Server.Kestrel[32]
      Connection id "0HLJA6SH4AF9Q", Request id "0HLJA6SH4AF9Q:00000001": the application completed without reading the entire request body.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] Request starting HTTP/1.1 POST https://localhost:5001/api/operations/deposit application/json 282
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Route matched with {action = "Post", controller = "Operations"}. Executing action API.Controllers.OperationsController.Post (API)
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method API.Controllers.OperationsController.Post (API) with arguments (API.Req.Deposit) - Validation state: Valid
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action method API.Controllers.OperationsController.Post (API), returned result Microsoft.AspNetCore.Mvc.ObjectResult in 4782.8378ms.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1]
      Executing ObjectResult, writing value of type 'API.Res.Deposit'.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action API.Controllers.OperationsController.Post (API) in 4901.4518ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 4930.5295ms 200 application/json; charset=utf-8

在 Startup.cs 中添加中间件后:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ...
    app.UseMiddleware<RequestResponseLoggingMiddleware>();
    app.UseHttpsRedirection();
    app.UseMvc();
}

整个日志将输出

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 POST http://localhost:5000/api/operations/deposit application/json 282
info: API.RequestResponseLoggingMiddleware[0]
      http localhost:5000/api/operations/deposit  
      {
        "merchant": "981001",
        ....,
        "userName": "susan"
      }
info: API.RequestResponseLoggingMiddleware[0]
      Response
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 50.7335ms 307
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 POST https://localhost:5001/api/operations/deposit application/json 282
info: API.RequestResponseLoggingMiddleware[0]
      https localhost:5001/api/operations/deposit  
      {
           "merchant": "981001",
           ...,
           "userName": "susan"
      }
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Route matched with {action = "Post", controller = "Operations"}. Executing action API.Controllers.OperationsController.Post (API)
info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1]
      Executing ObjectResult, writing value of type 'Microsoft.AspNetCore.Mvc.SerializableError'.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action API.Controllers.OperationsController.Post (API) in 179.1267ms
info: API.RequestResponseLoggingMiddleware[0]
      Response {"":["A non-empty request body is required."]}
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 213.3557ms 400 application/json; charset=utf-8

它发现了一个序列化问题,然后我尝试设置SuppressModelStateInvalidFilter如下:

public void ConfigureServices(IServiceCollection services)
{

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    services.Configure<ApiBehaviorOptions>(
        options => {options.SuppressModelStateInvalidFilter = true; });
}

日志显示更多信息,如下所示:

info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Route matched with {action = "Post", controller = "Operations"}. Executing action API.Controllers.OperationsController.Post (API)
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method API.Controllers.OperationsController.Post (API) with arguments () - Validation state: Invalid
      Object reference not set to an instance of an object.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action method API.Controllers.OperationsController.Post (API), returned result Microsoft.AspNetCore.Mvc.ObjectResult in 454.3309ms.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1]
      Executing ObjectResult, writing value of type 'API.Res.Deposit'.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action API.Controllers.OperationsController.Post (API) in 640.913ms
info: API.RequestResponseLoggingMiddleware[0]
      Response 
      {
         "branch": null,
         "holder": null,
         "number": null,
         "expire": "0001-01-01T00:00:00",
         "error": 0,
         "verifyText": null,
         "transactionId": null
      }
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 671.6427ms 200 application/json; charset=utf-8

一切都变为空。为什么请求上下文主体会丢失在中间件中?

标签: c#middlewareasp.net-core-webapi

解决方案


正如@PeterBons 指出的那样,问题已经解决。

我们需要设置request.EnableRewind();并在阅读完内容后将主体位置设置为 0 request.Body.Position = 0;。以下是我使用的代码:

private async Task<string> FormatRequest(HttpRequest request)
{
    request.EnableRewind();
    var buffer = new byte[Convert.ToInt32(request.ContentLength)];
    await request.Body.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
    var bodyAsText = Encoding.UTF8.GetString(buffer);
    request.Body.Position = 0;
    return $"{bodyAsText}";
}

快乐编码!


推荐阅读