我对IIS何时发送响应感到非常困惑,我真的很想知道它是如何工作的,因为我正在执行响应日志记录,并且我不想破坏正文。
这是我的日志记录中间件Invoke,在MVC中间件(控制器)之前调用。控制器返回其Ok方法后,响应是立即发送还是等待中间件的其余部分?如果以这种方式记录日志,是否有可能破坏响应?
public async Task Invoke(HttpContext context)
{
var requestResponseLog = new RequestResponseLog
{
RequestTime = DateTimeOffset.UtcNow,
Request = await FormatRequest(context)
};
Stream originalBody = context.Response.Body;
using (MemoryStream newResponseBody = _recyclableMemoryStreamManager.GetStream())
{
context.Response.Body = newResponseBody;
await _next(context);
newResponseBody.Seek(0, SeekOrigin.Begin);
await newResponseBody.CopyToAsync(originalBody);
newResponseBody.Seek(0, SeekOrigin.Begin);
requestResponseLog.ResponseTime = DateTimeOffset.UtcNow;
requestResponseLog.Response = await FormatResponse(context, newResponseBody);
_requestResponseHandler(requestResponseLog);
}
}
答案 0 :(得分:2)
将每个注册的中间件视为创建请求的步骤。您的invoke方法是该路径上的“您的”步骤。 await _next(context);
指示框架此时移至管道中的下一个中间件-但是-在其余中间件执行完毕后返回,以便可以再次拾取您的代码。
所以..考虑到这一点,让我们假设我们设置了3个中间件。管道的工作方式如下:
[要求输入]
Middleware-1 => Middleware-2 => Middleware-3
[已产生响应]
Middleware-3 => Middleware-2 => Middleware-1
[响应来电]
假设您将await _next(context)
添加到了Middleware2的Invoke方法中。当代码到达该点时,它会跳到管道中的下一个中间件,但是它知道在响应返回时就在那里停止。这样您就可以再次拦截它。
如果您正在记录请求,则您的自定义代码将在该await _next(context)
调用之前发送。如果您正在记录响应,它将在该调用之后出现。
注意:此外,中间件的排序由它们在Startup类中注册的顺序决定。