是这样的,我想实现请求日志记录的功能,能够记录每个请求连接的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,能不能都转成对应内容的字符串
既然是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;
});
}
}
嗨,你好。 你的代码我有点不理解,我想要实现用日志记录到每次请求的返回数据信息。你给示例代码中是替换掉response流 。 是不是替换它之后,在OnResultExecuted中调用Response.Body就行了呢?
@尾随前行: 那你加上context.Request.EnableBuffering();试试吧!
@Jonny-Xhl: 感谢回复,您说的意思我大概明白了。谢谢
一般记录请求log 是通过中间件Middlerware实现,如楼上。
你这里是在 ActionFilterAttribute 来实现的话,需要通过ActionExecutedContext.Result 来拿到Action的返回值。而非Response。因为这时候请求流程管道实际还未结束。
具体获取可以参考:
https://stackoverflow.com/questions/49013678/get-values-from-resultexecutedcontext-result
感谢回复,大概的意思我明白啦。 初学NET core,还比较生疏,请见谅。