Wachburn
Wachburn

Reputation: 2939

Simple middleware example. Invoke method dosn't continue processing

Here is a simple example: Middlewares:

public class AuthorizationMiddleware
{
    private readonly RequestDelegate _next;    
    public AuthorizationMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        if (context.Request.Headers.Keys.Contains("X-Not-Authorized"))
        {
            context.Response.StatusCode = 401; 
            return;
        }

        await _next.Invoke(context);
    }
}

public class RequestHeaderMiddleware
{
    private readonly RequestDelegate _next;    
    public RequestHeaderMiddleware(RequestDelegate next)
    {
        _next = next;
    }    
    public async Task Invoke(HttpContext context)
    {
        if (context.Request.Headers.Keys.Contains("X-Cancel-Request"))
        {
            context.Response.StatusCode = 500;
            return;
        }    
        await _next.Invoke(context);

        // not calling
        context.Response.Headers.Add("X-Transfer-Success", "true");
        await context.Response.WriteAsync("test");
    }
}

public class ProcessingTimeMiddleware
{
    private readonly RequestDelegate _next;    
    public ProcessingTimeMiddleware(RequestDelegate next)
    {
        _next = next;
    }    
    public async Task Invoke(HttpContext context)
    {
        var watch = new Stopwatch();
        watch.Start();

        await _next(context);

        context.Response.Headers.Add("X-Processing-Time-Milliseconds", new[] { watch.ElapsedMilliseconds.ToString() });
    }
}

registration:

 app.UseMiddleware<AuthorizationMiddleware>();
 app.UseMiddleware<RequestHeaderMiddleware>();
 app.UseMiddleware<ProcessingTimeMiddleware>();
 app.UseMvc(routes =>
 {
          routes.MapRoute(
              name: "default",
              template: "{controller=Home}/{action=Index}/{id?}");
 });

Why does this code await context.Response.WriteAsync("test"); not calling in the class? And it doesn't work only if I register MVC. How does MVC prevent continue method execution? Am I missed something in c# ?

Upvotes: 0

Views: 2719

Answers (2)

The Beginer
The Beginer

Reputation: 1

Try the code below:

context.Response.OnStarting(() =>
{
   context.Response.Headers.Add("X-Transfer-Success", "true");                 
});

// await context.Response.WriteAsync("test");

await _next(context);

Upvotes: 0

ssmith
ssmith

Reputation: 8922

If some middleware has already begun writing to the response, then you can't do things like editing the response headers. This is why the docs recommend against manipulating the headers after other middleware has run (e.g. on the way "out" of the stack, after calling _next.Invoke().

You should find a way to log the information you want that doesn't involve directly writing to the response. One approach is to simply log and store it on the server (cache, database) and view it in a separate request.

When you add MVC, it is going to send headers and start sending the body of the response as well. This is why your code that runs after MVC can no longer write to the response - it's been sent.

Upvotes: 4

Related Questions