Search code examples
c#asp.net-core.net-6.0minimal-apis

.NET6 minimal API: Manipulating response after .MapGet


I need to manipulate the JSON after each .MapGet() in the same way (apply some transformations).

I always thought that we can setup middleware on response pipeline as well as on request pipeline by placing .UseMiddleware() (or .Use()) after .MapGet() like that:

[...]
app.UseMiddleware<MyRequestMiddleware>(); //It should be invoked before .MapGet()
app.MapGet(...);
app.UseMiddleware<MyResponseMiddleware>(); //It should be invoked after .MapGet()
await app.RunAsync();

In reality MyRequestMiddleware and MyResponseMiddleware are both pipelined to run before .MapGet(). How can I achieve "response pipeline" to run some transformation function for every endpoint? I know I can create a DI injected service and invoke the transformation in each endpoint but I'd rather not change the .MapGet() implementations and separate the transformations in another layer.


Solution

  • In ASP.NET Core middlewares that run before also run after (in a way). The request handling pipeline is build in the way that earlier middleware is (optionally) calling the next one (docs).

    enter image description here

    So if you want a middleware which does something after the next one then you just implement it in the following way:

    public class MyMiddleware
    {
        private readonly RequestDelegate _next;
    
        public MyMiddleware(RequestDelegate next)
        {
            _next = next;
        }
    
        public async Task InvokeAsync(HttpContext context)
        {
            await _next(context);
    
            // your code that runs after the following middleware
        }
    }
    

    Or

    app.Use(async (context, next) =>
    {
        await next(context);
        // your code that runs after the following middleware
    });
    

    In this pattern you can write a single middleware which does something before AND after.

    app.MapGet(...) does not register middleware, it registers route handler. The middleware which handles routes is registered with UseRouting if I remember correctly (also explicit call to it is not required).

    See also How do I get the incoming request body and the outgoing response body in ASP.NET Core middleware?.