.NET Core MVC中间件使用记录日志
中间件是一种装配到应用管道以处理请求和响应的软件。 每个组件:
- 选择是否将请求传递到管道中的下一个组件。
- 可在管道中的下一个组件前后执行工作。
请求委托用于生成请求管道。 请求委托处理每个 HTTP 请求。
使用 RunMap 和 Use 扩展方法来配置请求委托。 可将一个单独的请求委托并行指定为匿名方法(称为并行中间件),或在可重用的类中对其进行定义。 这些可重用的类和并行匿名方法即为中间件,也叫中间件组件。 请求管道中的每个中间件组件负责调用管道中的下一个组件,或使管道短路。 当中间件短路时,它被称为“终端中间件”,因为它阻止中间件进一步处理请求。
将 HTTP 处理程序和模块迁移到 ASP.NET Core 中间件介绍了 ASP.NET Core 和 ASP.NET 4.x 中请求管道之间的差异,并提供了更多的中间件示例。
官网介绍地址:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-6.0
C# 全选
using Coldairarrow.Util;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Coldairarrow.Api
{
public class RequestLogMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public RequestLogMiddleware(RequestDelegate next, ILogger<RequestLogMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
Stopwatch watch = Stopwatch.StartNew();
string resContent = string.Empty;
//返回Body需特殊处理
Stream originalResponseBody = context.Response.Body;
using var memStream = new MemoryStream();
context.Response.Body = memStream;
try
{
await _next(context);
memStream.Position = 0;
resContent = new StreamReader(memStream).ReadToEnd();
memStream.Position = 0;
await memStream.CopyToAsync(originalResponseBody);
}
catch
{
throw;
}
finally
{
context.Response.Body = originalResponseBody;
watch.Stop();
if (resContent?.Length > 1000)
{
resContent = new string(resContent.Copy(0, 1000).ToArray());
resContent += "......内容太长已忽略";
}
string log =
@"方向:请求本系统
Url:{Url}
Time:{Time}ms
Method:{Method}
ContentType:{ContentType}
Body:{Body}
StatusCode:{StatusCode}
Response:{Response}
";
_logger.LogInformation(
log,
context.Request.Path,
(int)watch.ElapsedMilliseconds,
context.Request.Method,
context.Request.ContentType,
context.RequestServices.GetService<RequestBody>().Body,
context.Response.StatusCode,
resContent
);
}
}
}
}
C# 全选
using Coldairarrow.Util;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using System.Text;
using System.Threading.Tasks;
namespace Coldairarrow.Api
{
public class RequestBodyMiddleware
{
private readonly RequestDelegate _next;
public RequestBodyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if ((context.Request.ContentType ?? string.Empty).Contains("application/json"))
{
context.Request.EnableBuffering();
string body = await context.Request.Body?.ReadToStringAsync(Encoding.UTF8);
context.RequestServices.GetService<RequestBody>().Body = body;
}
await _next(context);
}
}
}
C# 全选
using Coldairarrow.Util;
namespace Coldairarrow.Api
{
public class RequestBody : IScopedDependency
{
public string Body { get; set; }
}
}
使用:
startUp.cs中
app.UseMiddleware<T>()
C# 全选
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//跨域
app.UseCors(x =>
{
x.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.DisallowCredentials();
})
.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
})
.UseMiddleware<RequestBodyMiddleware>()
.UseMiddleware<RequestLogMiddleware>()
.UseDeveloperExceptionPage()
.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "application/octet-stream"
})
.UseRouting()
.UseAuthentication()
.UseAuthorization()
.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireAuthorization();
})
.UseOpenApi()//添加swagger生成api文档(默认路由文档 /swagger/v1/swagger.json)
.UseSwaggerUi3()//添加Swagger UI到请求管道中(默认路由: /swagger).
;
}
版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
post 张国生