Home > Blockchain >  why writing to HttpContext.Response "short-circuit" MVC pipeline
why writing to HttpContext.Response "short-circuit" MVC pipeline

Time:07-16

below is the code:

public class Startup
{
   // ...
   public void Configure(IApplicationBuilder app)
   {
      app.UseRouting();

      app.Use(async (context, next) =>
      {
         await context.Response.WriteAsync("write sth first\n");
         await next();
      });

      app.UseEndpoints(endpoints =>
      {
         endpoints.MapControllers();
      });

   }
}

I got only "write sth first" response, the content generated by controller's action method is not appended to the response. However, I put a debugger on the action method of the controller, the debugger was hitting, which means the MVC pipeline was still running(which is not really short circuit) then why the response from action method is not in the response?

What's confusing me more is, if I change the code to:

public class Startup
{
   // ...
   public void Configure(IApplicationBuilder app)
   {
      app.UseRouting();

      app.Use(async (context, next) =>
      {
         await context.Response.WriteAsync("write sth first\n");
         await next();
      });

      app.UseEndpoints(endpoints =>
      {
         endpoints.MapGet("/", async context => {   
            await context.Response.WriteAsync("Hello World!");
         });
      });

   }
}

then I got a response that is "write sth first\n "Hello World!", so why this time the response from the endpoint is appended to the Response?

Is anywhere in endpoints.MapControllers() that check the HttpContext.Response like if there is content then abort the remaining process? where is the source code for this part?

CodePudding user response:

Here's the error when I tried

System.InvalidOperationException: Headers are read-only, response has already started.

So it has nothing to do with middleware or MVC pipelines. The controller needs to write HTTP headers but it cannot because the response has already started.

CodePudding user response:

Seeing as other middleware might also need to write to the Response, you shouldn't start writing to it yourself. You could try attaching to the OnStarting event instead. That way you won't start the Response yourself (Pseudocode from memory):

app.Use(async (context, next) =>
{
    context.Response.OnStarting(async () =>
    {
        await context.Response.WriteAsync("write sth first\n");
    });

    await next();
}

why this time the response from the endpoint is appended to the Response

That is because the endpoint middleware is called after your custom middleware. So first it calls your middleware, then it calls the endpoint middleware. Middleware order matters.

  • Related