“ASP.NET 5中间件”;没有收到任何答复”;添加标题后

“ASP.NET 5中间件”;没有收到任何答复”;添加标题后,asp.net,asp.net-web-api,asp.net-core,Asp.net,Asp.net Web Api,Asp.net Core,只要我添加了标题之类的内容。我无法再收到来自Web API控制器的任何响应 public class MyMiddleware { RequestDelegate _next; public MyMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { //await co

只要我添加了标题之类的内容。我无法再收到来自Web API控制器的任何响应

public class MyMiddleware
{
    RequestDelegate _next;

    public MyMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {

        //await context.Response.WriteAsync("Hello!");
        await _next(context);
        context.Response.Headers.Add("X-ElapsedTime", new[] { "bla" });
    }
}
我是否需要首先阅读以下中间件“UseMvc”生成的答案

我有一个非常简单的控制器方法:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
 {
     app.UseMyMiddleware();
     app.UseMvc();
 }
我找到了对的引用:并试图根据它构建代码


无论如何,这个代码感觉不是很安全。它真的是线程安全的。

基本上发生的事情是,在将任何内容写入响应主体之后,您不能设置任何头

这是因为标题在正文之前发送,并且只要设置了正文内容就可以发送

以适当的方式绕过它将是缓冲响应,并且在执行所有中间件之前不发送任何内容,以便它们有机会修改头。此行为应由web服务器负责。不幸的是,我没有找到任何关于如何在ASP.NET5(IIS或Kestrel)上配置缓冲的有用信息

您的解决方案似乎还可以,但它不是线程安全的。中间件是单例的,当多个并发请求可能击中您的服务器时,在类字段中保存上下文可能会引入竞争条件。 通过将上下文作为状态对象传递,可以使其线程安全

 public class MyMiddleware
{
    RequestDelegate _next;
    HttpContext _context;

    public MyMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    public async Task Invoke(HttpContext context)
    {
        _context = context;
        context.Response.OnStarting(OnStartingCallback, state: this);
        await _next(context);
    }
    public Task OnStartingCallback(object state)
    {
        _context.Response.Headers.Set("x-bla", "bla");
        return Task.FromResult(0);
    }
}

然后在回调中通过将
对象状态
转换为
HttpContext

来检索它。谢谢,听起来像是早期PHP开发中已经发送的HTTP头。“陈述:这”有意义吗?在这种特殊情况下,状态对象将始终指向同一个类实例。或者是按值调用。始终不确定它在C#中是按值调用还是按引用调用。它将始终指向MyMiddleware类的同一实例。但由于中间件只实例化一次,因此所有请求的实例都是相同的。这就是为什么你不应该在那里使用'this'关键字并传递上下文。我根据你的建议修改了我的代码(state:context)。如何向该上下文添加更多变量?我正在启动秒表来测量请求时间()
 public class MyMiddleware
{
    RequestDelegate _next;
    HttpContext _context;

    public MyMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    public async Task Invoke(HttpContext context)
    {
        _context = context;
        context.Response.OnStarting(OnStartingCallback, state: this);
        await _next(context);
    }
    public Task OnStartingCallback(object state)
    {
        _context.Response.Headers.Set("x-bla", "bla");
        return Task.FromResult(0);
    }
}
context.Response.OnStarting(OnStartingCallback, state: context);