好的,我正在与ILSpy进行交流,并试图弄清这里发生了什么,但是我运气不高。

在使用Razor引擎的ASP.NET MVC4应用程序中的给定视图中(尽管可以肯定,这适用于MVC3,可能是2),从OutputStack继承的WebPageBase属性只是TextWriter对象的堆栈。

通过推入和弹出该堆栈,可以操纵给定Razor视图的输出。我希望通过HTML helper扩展方法来利用它,但是我也注意到ViewContext,它也是HtmlHelper的公共成员,有它自己的TextWriter。

现在,我进行了快速检查:(从视图中)

@object.ReferenceEquals(this.ViewContext.Writer, this.OutputStack.Peek()) // True


但是,以下使我感到困惑:

@{
    // push one on
    OutputStack.Push(new StringWriter());
}
Hello!
@{
    // capture everything and pop it
    string buffer1 = OutputStack.Peek().ToString();
    OutputStack.Pop();
}
<pre>@(buffer1)</pre>

@{
    // apparently it references the top of the OutputStack
    // so this should be essentially the same
    var oldWriter = ViewContext.Writer;
    ViewContext.Writer = new StringWriter();
}
World!
@{
    // revert it and hope for the best
    string buffer2 = ViewContext.Writer.ToString();
    ViewContext.Writer = oldWriter;
}
<pre>@(buffer2)</pre>


以上结果如下:


Hello!被捕获到buffer1中,并实际上作为<pre>Hello!</pre>转储。这是预期和期望的。
另一方面,World!立即输出,随后是空的<pre></pre>块;换句话说,它没有捕获任何东西。


我的问题如下:这些TextWriter对象如何相互关联,为什么我不能像在ViewContext顶部一样通过OutputStack管理引用? (相反,如何通过ViewContext管理引用?)



附录
我碰到的细节和其他废话。


WriterViewContext属性不会丢弃传递给setter的值,因此在第二个示例中,它不只是将其删除。
沿着调用堆栈移动,OutputStack实际上来自PageContext
使用ViewContext.Writer属性WebViewPage.ExecutePageHierarchy()WebViewPage中设置Output,这是OutputStack的顶部! (仅仅是我一个人,还是开始看起来像老鼠的依赖巢?)

最佳答案

我将发表评论作为答案。它可能说明解决了您问题的学术部分,但肯定可以解决了问题的实际部分,最重要的是,您尝试解决的是最初的问题。

在您的助手中,您可以获取当前视图的OutputStack

public static void MyHelper(this HtmlHelper html)
{
    var stack = ((WebPageBase)html.ViewDataContainer).OutputStack;

    ... you could push and pop here and solve your real world problem
}

关于asp.net - TextWriter引用行为异常,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17557732/

10-11 22:44