首页 新闻 会员 周边 捐助

netcore3中,在OnResultExecuted方法中,怎么读取Response内容

0
悬赏园豆:10 [已解决问题] 解决于 2020-10-31 11:32

是这样的,我想实现请求日志记录的功能,能够记录每个请求连接的Request请求信息和Response输出信息。

现在OnResultExecuted方法中,能读取到Request的基本信息,但是Response输出的信息不知道怎么获取,使用下面的代码每次请求都进不了if里面

if (context.HttpContext.Response.Body.CanRead)
{
     var responseReader = new StreamReader(context.HttpContext.Response.Body);
     log.Response = responseReader.ReadToEnd();
}

我想要,不管这次请求是输出视图还是字符串还是json,能不能都转成对应内容的字符串

尾随前行的主页 尾随前行 | 初学一级 | 园豆:0
提问于:2020-10-27 13:45
< >
分享
最佳答案
0

既然是aspnet core那么Request和Response信息弄一个中间件拦截处理就好了。

大致思想如下:

    public class HttpContextMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger _logger;
        /// <summary>
        /// 计时器
        /// </summary>
        private Stopwatch _stopwatch;
        /// <summary>
        /// 构造 Http 请求中间件        
        /// <param name="next"></param>
        /// <param name="loggerFactory"></param>  
        /// </summary>
        public HttpContextMiddleware(RequestDelegate next,
            ILoggerFactory loggerFactory)
        {
            _next = next;
            _logger = loggerFactory.CreateLogger<HttpContextMiddleware>();
        }

        public async Task InvokeAsync(HttpContext context)
        {
            if (context.Request.Method == "GET")
            {
                await _next(context);
                return;
            }         
            context.Request.EnableBuffering();
            _stopwatch = new Stopwatch();
            _stopwatch.Start();
            //默认值           
            var request = context.Request.Body;
            var response = context.Response.Body;
            try
            {
                using (var newRequest = new MemoryStream())
                {
                    //替换request流
                    context.Request.Body = newRequest;
                    using (var newResponse = new MemoryStream())
                    {
                        //替换response流
                        context.Response.Body = newResponse;
                        using (var writer = new StreamWriter(newRequest))
                        {                           
                            newRequest.Position = 0;
                            context.Request.Body = newRequest;
                            await _next(context);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($" http中间件发生错误: " + ex.ToString());
                //定义返回类型
                context.Response.ContentType = "application/json";
                //错误异常的统一返回
                var exOutput = new OutputBaseDto
                {
                    ErrorMsg = ex.Message,
                    GroupID = log.GroupId,
                    RequestID = log.RequestId,
                    ResultCode = Application.Main.Dtos.ResultCode.InternetError
                };
                using (var sw = new StreamWriter(response))
                {
                    await sw.WriteAsync(exOutput.Obj2Json());
                    await sw.FlushAsync();
                }
                //数据库记录堆栈
                exOutput.ErrorMsg += ex.StackTrace;
                log.Response = exOutput.Obj2Json();
            }
            finally
            {
                context.Request.Body = request;
                context.Response.Body = response;
            }

            // 响应完成时存入缓存
            context.Response.OnCompleted(() =>
            {
                _stopwatch.Stop();
                return Task.CompletedTask;
            });
        }
    }
收获园豆:7
Jonny-Xhl | 小虾三级 |园豆:691 | 2020-10-27 14:21

嗨,你好。 你的代码我有点不理解,我想要实现用日志记录到每次请求的返回数据信息。你给示例代码中是替换掉response流 。 是不是替换它之后,在OnResultExecuted中调用Response.Body就行了呢?

尾随前行 | 园豆:0 (初学一级) | 2020-10-27 18:53

@尾随前行: 那你加上context.Request.EnableBuffering();试试吧!

Jonny-Xhl | 园豆:691 (小虾三级) | 2020-10-28 09:28

@Jonny-Xhl:  感谢回复,您说的意思我大概明白了。谢谢 

尾随前行 | 园豆:0 (初学一级) | 2020-10-31 11:31
其他回答(1)
0

一般记录请求log 是通过中间件Middlerware实现,如楼上。
你这里是在 ActionFilterAttribute 来实现的话,需要通过ActionExecutedContext.Result 来拿到Action的返回值。而非Response。因为这时候请求流程管道实际还未结束。

具体获取可以参考:
https://stackoverflow.com/questions/49013678/get-values-from-resultexecutedcontext-result

收获园豆:3
gt1987 | 园豆:1150 (小虾三级) | 2020-10-29 09:59

感谢回复,大概的意思我明白啦。 初学NET core,还比较生疏,请见谅。

支持(0) 反对(0) 尾随前行 | 园豆:0 (初学一级) | 2020-10-31 11:31
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册