“ASP.NET 5中间件”;没有收到任何答复”;添加标题后
只要我添加了标题之类的内容。我无法再收到来自Web API控制器的任何响应“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
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);