I've been trying to understand how ASP.NET 5 pipeline middlewares really work. A middleware, as I know, is just a Func<RequestDelegate, RequestDelegate>
, which is a pointer to a method that receives a reference to the next request delegate and returns a new one that wraps the next. We can of course, use a class to represent a middleware, something like:
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
}
}
Since the RequestDelegate
is a delegate that can hold references to methods which receives one HttpContext
and returns a Task
the Invoke
method is the request delegate to be returned and which has access to the next one on the pipeline.
We have then, when coding a middleware, access to the next component of the pipeline, but there is a doubt I have. In the beginning I thought the ideal was always to work the following way:
- Check if the middleware can handle the request
- If it can, do whatever must be done with the
HttpContext
- Call the next middleware on the pipeline
So that when I studied this for the first time I thought each middleware should always call the next one. But doing this led to strange behavior as discussed on this question.
Also looking at the source code of some middlewares I see some of them follow another steps:
- Check if the middleware can handle the request
- If it can, do whatever must be done with the
HttpContext
and that's all - If not, and only if not call the next one
Is this the real idea of using middlewares? Which way is the correct approach at this? Each middleware do what must be done with the request and always invoke the next or if a midleware can handle the request it doesn't invoke the next anymore?
I believe a middleware should call the next only if it can't handle the request. The reason I think that is because if not, there would be coupling between the middlewares on the pipeline. So that to process the request the middleware would need to be aware of what the previous one did to avoid messing everything. Is this conclusion right?