我是ASP.NET Core的新手。 我正在尝试将旧项目迁移到ASP.NET核心。 我们在部分内部使用了许多脚本块,这些脚本块在预定义的布局位置集中呈现。我们使用带有一次性模式的HtmlHelper,如here所述。问题是由于ASP.NET核心中的新架构,不可能使用
webPageBase.OutputStack.Pop()
抓住内容。我找到了与TagHelpers类似的解决方案 但是我仍然会继续使用HtmlHelper扩展来收集脚本逻辑并在单个位置渲染。否则我将需要编写2个标记帮助程序,协调它们并将HtmlHelper扩展的所有50-100个数字替换为标记帮助程序。
答案 0 :(得分:1)
HTML帮助程序仍然是ASP.NET Core中的一个东西。仅仅因为标记帮助程序是呈现自定义HTML的新的且通常更灵活的解决方案,这并不意味着HTML帮助程序已经消失或者它们没有用处。内置标记帮助程序实际上基于HTML帮助程序,并将使用相同的内部后端来生成输出。所以它只是同一个不同的界面。
话虽如此,由于ASP.NET Core呈现视图的方式,捕获using
块内的内容比在标记帮助程序中的工作方式(它是一个非常通用的功能)要困难一些。
我现在已经坐了一会儿,想出了以下内容。只要块打开,暂时将视图编写器替换为StringWriter
即可。 请注意,这可能是一个非常糟糕的主意。但它确实有效......
public static class ScriptHtmlHelper
{
private const string ScriptsKey = "__ScriptHtmlHelper_Scripts";
public static ScriptBlock BeginScripts(this IHtmlHelper helper)
{
return new ScriptBlock(helper.ViewContext);
}
public static IHtmlContent PageScripts(this IHtmlHelper helper)
{
if (helper.ViewContext.HttpContext.Items.TryGetValue(ScriptsKey, out var scriptsData) && scriptsData is List<object> scripts)
return new HtmlContentBuilder(scripts);
return HtmlString.Empty;
}
public class ScriptBlock : IDisposable
{
private ViewContext _viewContext;
private TextWriter _originalWriter;
private StringWriter _scriptWriter;
private bool _disposed;
public ScriptBlock(ViewContext viewContext)
{
_viewContext = viewContext;
_originalWriter = viewContext.Writer;
// replace writer
viewContext.Writer = _scriptWriter = new StringWriter();
}
public void Dispose()
{
if (_disposed)
return;
try
{
List<object> scripts = null;
if (_viewContext.HttpContext.Items.TryGetValue(ScriptsKey, out var scriptsData))
scripts = scriptsData as List<object>;
if (scripts == null)
_viewContext.HttpContext.Items[ScriptsKey] = scripts = new List<object>();
scripts.Add(new HtmlString(_scriptWriter.ToString()));
}
finally
{
// restore the original writer
_viewContext.Writer = _originalWriter;
_disposed = true;
}
}
}
}
用法如下:
@using (Html.BeginScripts()) {
<script>console.log('foo');</script>
<script>console.log('bar');</script>
}
@using (Html.BeginScripts()) {
<script>console.log('baz');</script>
}
然后渲染一切:
@Html.PageScripts()