.net Core 中介軟體記錄出入引數,異常資訊
阿新 • • 發佈:2021-02-02
文章目錄
中介軟體記錄全域性日誌/出入引數:
日誌記錄中介軟體
遇到的問題(踩過的坑)
-
- Specified method is not supported. 不支援指定的方法
-
- Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead. 不允許同步操作。
-
- Stream was not readable. 流不可讀取
-
- A non-empty request body is required. 空的請求主體
-
- Concurrent reading is not supported. 不支援併發讀取
Stream was not readable. 流不可讀取/Specified method is not supported. 不支援指定的方法
.net Core 3的Request.Body預設不允許設定位置,不允許讀取等
//啟用讀取request
httpContext.Request.EnableBuffering();
Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead. 不允許同步操作。
發生原因: .net Core 3以上Request.Body的流不允許同步讀取,使用
var requestContent = await requestReader.ReadToEndAsync(); 非同步讀取
await/ReadToEndAsync().Result; 同步讀取值
A non-empty request body is required. 空的請求主體
在讀取完後日志記錄下來,報這個錯誤,對比發現Body流的位置不在0了,導致控制器模型繫結的時候報錯.
request.Body.Position = 0;
完整程式碼
public async Task InvokeAsync(HttpContext httpContext)
{
//啟用讀取request
httpContext.Request.EnableBuffering();
//請求body
using var requestReader = new StreamReader(request.Body);
var requestContent = await requestReader.ReadToEndAsync();
request.Body.Position = 0;
//設定stream存放ResponseBody
var responseOriginalBody = response.Body;
using var memStream = new MemoryStream();
response.Body = memStream;
// 執行其他中介軟體
await _next(httpContext);
//處理執行其他中介軟體後的ResponseBody
memStream.Position = 0;
var responseReader = new StreamReader(memStream);
var responseContent = await responseReader.ReadToEndAsync();
memStream.Position = 0;
await memStream.CopyToAsync(responseOriginalBody);
response.Body = responseOriginalBody;
this._factory.CreateLogger<LogRequestMiddleware>().LogInformation($"請求方式: {request.Method} URL: {reqUrl} \r\n 引數: {requestContent}\r\n \r\n ");
this._factory.CreateLogger<LogRequestMiddleware>().LogInformation($"日誌返回: {request.Method} URL: {reqUrl} \r\n 引數: {responseContent}\r\n \r\n ");
}
異常記錄中介軟體
非常簡單,沒什麼可說的
/// <summary>
/// 異常記錄中介軟體
/// </summary>
public class ExceptionMiddleware
{
private readonly RequestDelegate _next;
private ILoggerFactory _factory;
/// <summary>
/// 異常
/// </summary>
/// <param name="next"></param>
/// <param name="factory"></param>
public ExceptionMiddleware(RequestDelegate next, ILoggerFactory factory)
{
_next = next;
this._factory = factory;
}
public async Task Invoke(HttpContext httpContext)
{
try
{
await _next.Invoke(httpContext);
}
catch (Exception ex)
{
await HandleError(httpContext, ex);
}
}
/// <summary>
/// 錯誤資訊處理方法
/// </summary>
/// <param name="context"></param>
/// <param name="ex"></param>
/// <returns></returns>
private async Task HandleError(HttpContext context, Exception ex)
{
context.Response.StatusCode = 500;
context.Response.ContentType = "application/json;";
string errorMsg = $"\r\n錯誤訊息:{ex.Message}{Environment.NewLine}\r\n錯誤追蹤:{ex.StackTrace}";
this._factory.CreateLogger<LogRequestMiddleware>().LogError(errorMsg);
//處理各種異常
ResponseBase<object> response = ResponseBase<object>.Error("系統錯誤");
var respStr = response.ToJson();
var by = Encoding.UTF8.GetBytes(respStr);
await context.Response.Body.WriteAsync(by, 0, by.Length);
}
}
使用方法
寫在跨域/路由/靜態目錄等系統中介軟體之後, 控制器中介軟體之前.
app.UseMiddleware();
app.UseMiddleware();