.net Core 中间件记录出入参数,异常信息


中间件记录全局日志/出入参数:

日志记录中间件

遇到的问题(踩过的坑)

    • 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();

.Net Core 过滤器记录全局日志/出参入参

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
.NET Core中,中间件负责处理HTTP请求和响应。中间件可以在请求到达控制器之前对请求进行操作,或在响应离开控制器之前对响应进行操作。 如果中间件无法正确读取请求参数,可能有几个原因导致这种情况。以下是一些可能的原因和解决方法: 1. 请求参数绑定问题:中间件可能无法正确绑定请求参数到控制器的操作方法参数上。可以检查控制器的操作方法参数的类型和名称是否与请求参数匹配,以确保正确绑定。 2. 请求体读取问题:如果请求中包含了请求体,中间件需要正确读取请求体才能获取请求参数。可以使用`Request.Body`对象来读取请求体,并使用适当的方法(如`StreamReader`)将其转换为字符串或JSON对象。 3. 请求头问题:某些请求参数可能包含在请求头中而不是请求体中。可以通过`Request.Headers`对象来读取请求头,并使用适当的方法(如`Get(key)`)获取特定请求头的值。 4. 中间件顺序问题:如果在中间件管道中使用了多个中间件,确保它们的顺序正确。有时,其他中间件可能已经处理了请求参数,导致当前中间件无法正确读取参数。可以尝试调整中间件的顺序,确保它在其他可能影响请求参数中间件之前执行。 5. 异常处理问题:如果中间件在读取请求参数时发生异常,可能会阻止其他中间件正确处理请求参数。可以通过在中间件代码中添加适当的错误处理逻辑来捕获并处理异常,以确保请求参数可以正确读取。 请根据具体情况检查以上可能的原因,并相应地调整中间件代码,以确保能正确读取请求参数

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值