Middleware Invoke called only on Request (but not on Response)

Viewed 36

I have a controller action that when called from client goes through the JwtMiddleware Invoke method. But when I return from the action using BaseController Ok method method Invoke is not called. Is that correct behaviour?

1 Answers

Yes. As described in the docs the middleware class must include:

  • A public constructor with a parameter of type RequestDelegate.
  • A public method named Invoke or InvokeAsync. This method must:
    • Return a Task.
    • Accept a first parameter of type HttpContext.

And sample Invoke(Async) method can look like this:

public async Task InvokeAsync(HttpContext context)
{
    // Do something before the next delegate/middleware
    // ...

    // Call the next delegate/middleware in the pipeline. 
    // (actually can be not invoked in some cases, i.e. if request is already handled by current middleware)
    await _next(context);

    // Do something after the next delegate/middleware in the pipeline has finished.
    // ...
}

So the pipeline is architectured in a way that the Invoke(Async) method itself is called once per middleware registration during the request, but it can handle/process the request before and after next registered delegate/middleware in the pipeline.

There is another alternative to middlewares for MVC (they are introduced for Minimal APIs in not released yet .NET 7 also but look more like endpoint specific middlewares) called filters which allow to distinguish between before and after action execution:

enter image description here

public class SampleActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
    }
}
Related