【问题标题】:Endpoints and custom middleware cause exceptions端点和自定义中间件导致异常
【发布时间】:2021-05-23 17:17:24
【问题描述】:

我有一个自定义中间件:

app.Use(async (context, next) => {
            await context.Response
            .WriteAsync($"Before \n");
            await next();
            await context.Response
            .WriteAsync($"After \n"); 
        });

和端点:

app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });

问题是它抛出了一个异常:

应用程序抛出了未处理的异常。 System.InvalidOperationException:标头是只读的,响应已经开始。

但是当我的中间件看起来像这样时:

app.Use(async (context, next) => {
            await next();
            await context.Response
            .WriteAsync($"After \n"); 
        });

一切正常。为什么只能在返回管道中修改响应。

当我像这样使用endpoints.Map.Get而不是endpoints.MapControllerRoute时:

app.UseEndpoints(endpoints => {
                endpoints.MapGet("/", async context => { 
                await context.Response.WriteAsync("Hello World!");
                });
            });

在这两种情况下一切正常。我知道这可能是一个愚蠢的问题,但我想问为什么当我使用endpoints.MapControllerRoute 时我不能在它通过管道之前修改响应?它说响应已经开始,那么为什么只能在返回路径中修改它而不是在处理请求时修改它?不应该反过来吗。

【问题讨论】:

    标签: c# asp.net asp.net-mvc asp.net-core


    【解决方案1】:

    一旦您向正文写入内容,HTTP 标头就会最终确定,并且无法再写入任何标头。但是,在您的 await next() 调用中,MVC 管道中内置的中间件尝试写入标头并失败。当您直接使用MapGet 时,不会执行其他中间件,因此一旦完成,就不会尝试写入标头,因此您的代码将执行属性。

    【讨论】:

    • 你能解释得更透彻吗? 一旦你写了一些东西到 body 你的意思是用await context.Response.WriteAsync($"After \n"); 写东西? 当你直接使用 MapGet 时,没有其他中间件被执行 你这是什么意思。和endpoints.MapControllerRoute不一样吗?
    • 是的,一个 HTTP 响应是由一个 header 和 body 组成的,而 body 是实际的内容(headers 存储了 cookie 之类的元数据)。由于标题首先出现,为了在正文中传输任何内容,您必须标记标题的结尾。 endpoints.MapControllerRoute 意味着除了你自定义的中间件之外,请求还会经过几个内置的中间件,比如 MVC。 docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多