c# - 在.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
一切都变为空。为什么请求上下文主体会丢失在中间件中?
解决方案
正如@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}";
}
快乐编码!
推荐阅读
- performance - OpenCL clCreateContextFromType 函数导致内存泄漏
- driver - 可签名性未通过 Windows 驱动程序测试
- python - 解开双循环内的递归以避免堆栈溢出
- css - 最大内容的 minmax() 不可能?
- julia - 如何在 Julia 中将向量(列表)广播到元组中?
- python-3.x - 创建并使用 WAV 文件作为对象 Python
- list - 实现自己的 Union 功能而无需两次遍历列表
- python - 我是否需要将 OS 或 Math 等基本模块放入新的 conda 环境中?
- r - 混淆矩阵敏感性和特异性长度匹配,但数据的级别不能多于参考
- excel - 在 Excel 中使用 VBA Round 函数时出现“无效的过程调用或语句”