Asp.Net Core 3.1 每次请求记录接口访问日志
我们总是有记录操作日志的需求,很早以前可以使用ActionFilter来实现,现在可已使用自定义中间键的方法
- 首先定义RequestResponseLoggingMiddleware中间件。说明这里日志记录通过Repository记录在数据库中,有其他需求的同学可以自定义这块,比如想通过nlog或log4net记录日志
public class RequestResponseLoggingMiddleware
{
private readonly RequestDelegate _next;
private RequestResponseLog _logInfo;
public RequestResponseLoggingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
_logInfo = new RequestResponseLog();
var serviceProvider = context.RequestServices;
var logRepo = (IAsyncRepository<Log>)serviceProvider.GetService(typeof(IAsyncRepository<Log>));
HttpRequest request = context.Request;
_logInfo.Url = request.Path.ToString();
_logInfo.Headers = request.Headers.ToDictionary(k => k.Key, v => string.Join(";", v.Value.ToList()));
_logInfo.Method = request.Method;
_logInfo.ExcuteStartTime = DateTime.Now;
//获取request.Body内容
if (request.Method.ToLower().Equals("post"))
{
HttpRequestRewindExtensions.EnableBuffering(request); //启用倒带功能,就可以让 Request.Body 可以再次读取
Stream stream = request.Body;
request.Body.Position = 0;
StreamReader sr = new StreamReader(request.Body);
string bodyContent = await sr.ReadToEndAsync();
_logInfo.RequestBody = bodyContent;
request.Body.Position = 0;
}
else if (request.Method.ToLower().Equals("get"))
{
_logInfo.RequestBody = request.QueryString.Value;
}
//获取Response.Body内容
var originalBodyStream = context.Response.Body;
using (var responseBody = new MemoryStream())
{
context.Response.Body = responseBody;
await _next(context);
_logInfo.ResponseBody = await FormatResponse(context.Response);
_logInfo.ExcuteEndTime = DateTime.Now;
await logRepo.AddAsync(new Log
{
User = "admin",
Content = _logInfo.ToString(),
CreateTime = DateTime.Now
});
await logRepo.SaveChangesAsync();
await responseBody.CopyToAsync(originalBodyStream);
}
}
private async Task<string> FormatResponse(HttpResponse response)
{
response.Body.Seek(0, SeekOrigin.Begin);
var text = await new StreamReader(response.Body).ReadToEndAsync();
response.Body.Seek(0, SeekOrigin.Begin);
return text;
}
}
public static class RequestResponseLoggingMiddlewareExtensions
{
public static IApplicationBuilder UseRequestResponseLogging(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestResponseLoggingMiddleware>();
}
}
2.在Startup的Configure中add中间件
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRequestResponseLogging();
}