自定义 WebViewPage 在渲染 Razor 模板时注入代码
Custom WebViewPage inject code when razor template is rendering
我正在尝试创建自定义 Razor 视图基础 class(继承 WebViewPage
),它将为每个呈现的视图模板(包括布局和部分视图),以便我在客户端上参考每个 Razor 模板的开始位置(对其结束位置不感兴趣)。
到目前为止我尝试过的是
- 覆盖 Write 方法(如注释 here 中所述)。这会在每个剃须刀部分注入代码,而不仅仅是每个模板一次(例如,每次您使用 HTML.TextBoxFor)
- 覆盖 ExecutePageHierarchy 方法(如上面 link 的 post 中所述)。每次遇到第一个
PopContext
调用时都会抛出一个错误:The "RenderBody" method has not been called for layout page "~/Views/Shared/_Layout.cshtml".
觉得我现在有答案了:
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
{
}
似乎可行,但如果有人有更好的解决方案,请分享。
在尝试了您的解决方案后,我在呈现 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);
}
我正在尝试创建自定义 Razor 视图基础 class(继承 WebViewPage
),它将为每个呈现的视图模板(包括布局和部分视图),以便我在客户端上参考每个 Razor 模板的开始位置(对其结束位置不感兴趣)。
到目前为止我尝试过的是
- 覆盖 Write 方法(如注释 here 中所述)。这会在每个剃须刀部分注入代码,而不仅仅是每个模板一次(例如,每次您使用 HTML.TextBoxFor)
- 覆盖 ExecutePageHierarchy 方法(如上面 link 的 post 中所述)。每次遇到第一个
PopContext
调用时都会抛出一个错误:The "RenderBody" method has not been called for layout page "~/Views/Shared/_Layout.cshtml".
觉得我现在有答案了:
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
{
}
似乎可行,但如果有人有更好的解决方案,请分享。
在尝试了您的解决方案后,我在呈现 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);
}