【问题标题】:How in asp.net core HtmlHelper extension with IDisposable pattern to catch inner content如何在带有 IDisposable 模式的 asp.net core HtmlHelper 扩展中捕获内部内容
【发布时间】:2019-11-16 04:19:20
【问题描述】:

我是 ASP.NET Core 的新手。 我正在尝试将我们的旧项目迁移到 ASP.NET 核心。 我们在局部中使用了很多脚本块,这些脚本块在预定义的布局位置集中呈现。我们使用具有一次性模式的 HtmlHelper,如 here 所述。问题是由于 ASP.NET 核心中的新架构,它无法使用

webPageBase.OutputStack.Pop()

捕捉内容。我找到了与TagHelpers 类似的解决方案 但我仍然更喜欢使用 HtmlHelper 扩展来收集脚本逻辑并在一个地方进行渲染。否则我将需要编写 2 个标签助手,协调它们并将所有 50-100 次出现的 HtmlHelper 扩展替换为标签助手。

【问题讨论】:

  • 您没有为脚本使用razor sections 有什么原因吗?
  • 是的。部分不适用于具有不同层次结构的部分。

标签: c# asp.net-core


【解决方案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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2013-07-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多