以下是代码:
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();
});
}
}
我只得到了“先写东西”的回复,控制器的动作方法生成的内容没有附加到响应中。但是,我把调试器放在控制器的动作方法上,调试器命中了,这意味着MVC管道还在运行(这并不是真正的短路),那么为什么动作方法的响应不在响应中呢?
更让我困惑的是,如果我将代码更改为:
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!");
});
});
}
}
然后我得到了一个响应,即“首先写某物\n你好世界!”,那么为什么这次来自端点的响应被附加到响应中呢?
endpoints.MapControllers()
中是否有检查HttpContext.Response
的地方,比如是否有内容,然后中止剩余的进程?这个部分的源代码在哪里?
发布于 2022-07-15 16:17:17
这是我尝试的错误
System.InvalidOperationException: Headers are read-only, response has already started.
因此,它与中间件或MVC管道无关。控制器需要写入HTTP头,但它不能写入,因为响应已经启动。
发布于 2022-07-15 16:45:46
考虑到其他中间件也可能需要写入Response
,您不应该自己开始编写它。您可以尝试将其附加到OnStarting
事件。这样,您就不会自己启动响应(从内存中伪代码):
app.Use(async (context, next) =>
{
context.Response.OnStarting(async () =>
{
await context.Response.WriteAsync("write sth first\n");
});
await next();
}
为什么这一次来自端点的响应被附加到响应
这是因为端点中间件是在定制中间件之后调用的。因此,它首先调用您的中间件,然后调用端点中间件。中间件订单很重要。
发布于 2022-07-18 19:24:50
基于tia的回答,我试图替换默认的响应体,并且Response.HasStarted属性为false,您可以看到页面是用启动时间和结束时间呈现的,context.Response.WriteAsync不会短路管道:
app.Use(async (context, next) =>
{
var response = context.Response;
var responseOriginalBody = response.Body;
using var memStream = new MemoryStream();
response.Body = memStream;
await context.Response.WriteAsync(string.Format("<a>starttime:{0}</a>", DateTime.Now.ToString("yyyy/MM/dd/HH:mm:ss.fff")));
var start = context.Response.HasStarted;
await next.Invoke();
await context.Response.WriteAsync(string.Format("<a>endtime:{0}</a>", DateTime.UtcNow.ToString("yyyy/MM/dd/HH:mm:ss.fff")));
memStream.Position = 0;
await memStream.CopyToAsync(responseOriginalBody);
response.Body = responseOriginalBody;
});
结果:
https://stackoverflow.com/questions/72995789
复制相似问题