IResultFilter不一致地写入响应

问题描述

我有以下代码

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {            
        services.AddMvc().AddMvcoptions(options =>
        {
            options.Filters.Add(new MessageAttribute("This is the Globally-Scoped Filter"));
        });
    }

    public void Configure(IApplicationBuilder app,IHostingEnvironment env)
    {
        app.UseMvcWithDefaultRoute();
    }
}

public class MessageAttribute : ResultFilterattribute
{
    private string message;
    public MessageAttribute(string msg)
    {
        message = msg;
    }

    public override void OnResultExecuting(ResultExecutingContext context)
    {
        WriteMessage(context,$"<div>Before Result:{message}</div>");
    }

    public override void OnResultExecuted(ResultExecutedContext context)
    {
        WriteMessage(context,$"<div>After Result:{message}</div>");
    }

    private void WriteMessage(FilterContext context,string msg)
    {
        var bytes = Encoding.ASCII.GetBytes($"<div>{msg}</div>");
        context.HttpContext.Response.Body.Write(bytes,bytes.Length);
    }
}

[Message("This is the Controller-Scoped Filter",Order = 10)]
public class HomeController : Controller
{
    [Message("This is the First Action-Scoped Filter",Order = 1)]
    [Message("This is the Second Action-Scoped Filter",Order = -1)]
    public ViewResult Index()
    {
        return View("Message",$"This is the {nameof(Index)} action on the {nameof(HomeController)}");
    }
}

当我按下Index()操作方法时。我得到以下三个输出之一:

1)

Before Result:This is the Second Action-Scoped Filter
Before Result:This is the Globally-Scoped Filter
Before Result:This is the First Action-Scoped Filter
Before Result:This is the Controller-Scoped Filter
After Result:This is the Controller-Scoped Filter
After Result:This is the First Action-Scoped Filter
After Result:This is the Globally-Scoped Filter
After Result:This is the Second Action-Scoped Filter
Before Result:This is the Second Action-Scoped Filter
Before Result:This is the Globally-Scoped Filter
Before Result:This is the First Action-Scoped Filter
Before Result:This is the Controller-Scoped Filter

空白页

页面加载时,通常为2),但有时为3)。刷新后,有时会给我1),但是不断刷新页面会给我随机结果,偏向2)和3)。

如果我在WriteMessage()中放置一个断点,让它断点,然后继续执行,它将得到预期的1)输出

为什么这种不一致的行为发生?

解决方法

来自Pro ASP.NET Core MVC 2的作者Adam Freeman,我从以下位置获得了代码片段:

在2.0版中,直到 管道已处理请求。在2.1中,更改后, 内容一生成就写出响应。当您尝试 加上,ASP.NET Core变得困惑,因为它需要更新 Content-Length标头,但不能,因为响应正在 已经写出来了。

由于您创建了比赛而出现不一致的结果 健康)状况。有时,您的过滤器会在 线程被分配以将其写出,有时却没有。 您可以使用本书中指定的ASP.NET Core版本,也可以更新代码,以便在action方法呈现其视图后,它不会尝试修改响应。