在渲染razor模板时,自定义WebViewPage注入代码

时间:2015-01-09 12:02:55

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

我正在尝试创建一个自定义Razor视图基类(继承WebViewPage),它将为每个正在呈现的视图模板注入一些HTML(包括布局和部分视图),以便我有一个参考每个Razor模板开始的客户端(对结束的位置不感兴趣)。

到目前为止我尝试过的是

  1. 覆盖Write方法(如评论here中所述)。这会在每个剃刀部分注入代码,而不是每个模板注入一次(例如,每次使用HTML.TextBoxFor时)
  2. 覆盖ExecutePageHierarchy方法(如上面链接的帖子中所述)。每次遇到第一次PopContext来电时,都会引发错误:The "RenderBody" method has not been called for layout page "~/Views/Shared/_Layout.cshtml".

2 个答案:

答案 0 :(得分:4)

在尝试解决方案之后,我对使用部分视图的复杂页面的渲染HTML产生了一些问题。

我的问题是一切都逆转了。 (部分观点的顺序)

要更正 - 我最终更换了OutputStack中的输出流

    public override void ExecutePageHierarchy()
    {

        // Replace output stream with a fake local stream
        StringWriter fakeOutput = new StringWriter();

        // Save output stack top level stream, and replace with fake local stream
        TextWriter outputStackTopOutput = OutputStack.Pop();
        OutputStack.Push(fakeOutput);

        // Run Razor view engine
        base.ExecutePageHierarchy();

        string content = fakeOutput.ToString();
        // Set back real outputs, and write to the real output 
        OutputStack.Pop();
        OutputStack.Push(outputStackTopOutput);
        outputStackTopOutput.Write(content);
    }

答案 1 :(得分:1)

认为我现在有一个答案:

public abstract class CustomWebViewPage: WebViewPage
{
    public override void ExecutePageHierarchy()
    {
        var layoutReferenceMarkup = @"<script type=""text/html"" data-layout-id=""" + TemplateInfo.VirtualPath + @"""></script>";

        base.ExecutePageHierarchy();
        string output = Output.ToString();

        //if the body tag is present the script tag should be injected into it, otherwise simply append
        if (output.Contains("</body>"))
        {
            Response.Clear();
            Response.Write(output.Replace("</body>", layoutReferenceMarkup+"</body>"));
            Response.End();
        }
        else
        {
            Output.Write(layoutReferenceMarkup);
        }
    }
}

public abstract class CustomWebViewPage<TModel>: CustomWebViewPage
{
}

似乎有效,但如果有人有更好的解决方案,请分享。