简单的中间件示例。调用方法不能继续处理

时间:2017-02-06 16:53:41

标签: c# asp.net-core

这是一个简单的例子: 中间件:

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() });
    }
}

注册:

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

为什么这段代码await context.Response.WriteAsync("test");没有在课堂上调用?它只有在我注册MVC时才有用。 MVC如何阻止继续执行方法?我错过了c#中的内容吗?

2 个答案:

答案 0 :(得分:3)

如果某些中间件已经开始写入响应,则您无法执行编辑响应标头等操作。这就是为什么docs建议不要在其他中间件运行之后操纵头文件(例如,在调用_next.Invoke()之后,在堆栈的路上&#34; out&#34 ;.

您应该找到一种方法来记录您想要的信息并不直接写入响应。一种方法是简单地将其记录并存储在服务器(缓存,数据库)上,并在单独的请求中查看它。

当您添加MVC时,它将发送标头并开始发送响应正文。这就是为什么在MVC之后运行的代码无法再写入响应的原因 - 它已被发送。

答案 1 :(得分:0)

尝试以下代码:

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

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

await _next(context);