我一直在尝试理解ASP.NET 5管道中间件的工作原理。据我所知,一个中间件只是一个Func<RequestDelegate, RequestDelegate>
,它是一个指向接收对下一个请求代理的引用并返回包装下一个请求代理的新请求代理的方法的指针。当然,我们可以使用类来表示一个中间件,例如:
public class MyMiddleware
{
private readonly _next;
public MyMiddleware(RequestDelegate next)
{
if (next == null)
{
throw new ArgumentNullException("next");
}
_next = next;
}
public Task Invoke(HttpContext context)
{
// New request delegate code here which can wrap the next one on the pipeline
}
}
由于RequestDelegate
是一个委托,可以持有接收一个HttpContext
并返回一个Task
的方法的引用,因此Invoke
方法是要返回的请求委托,并且可以访问管道中的下一个委托。
因此,在编写中间件时,我们可以访问管道的下一个组件,但我有一个疑问。一开始我认为理想的方式总是按以下方式工作:
- 检查中间件是否能够处理请求
- 如果可以,请执行必须在
HttpContext
中执行的操作 - 调用管道上的下一个中间件
因此,当我第一次学习这个东西时,我认为每个中间件应该始终调用下一个中间件。但是这样做会导致奇怪的行为,如此问题所述。
此外,查看一些中间件的源代码,我发现其中一些遵循另一些步骤:
- 检查中间件是否能够处理请求
- 如果可以,请执行必须在
HttpContext
中执行的操作 - 否则,只有在无法处理时才调用下一个中间件
这是使用中间件的真正思路吗?哪种方式是正确的?每个中间件都对请求执行必须的操作并始终调用下一个中间件,还是如果中间件可以处理请求,则不再调用下一个中间件?
我认为中间件应该只有在无法处理请求时才调用下一个中间件。我之所以这样认为是因为如果不这样做,就会在管道上产生耦合。因此,为了处理请求,中间件需要知道前一个中间件所做的内容以避免出现问题。这个结论正确吗?