.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 张国生  
 

