c# - HtmlHelper 在使用中使用 html/文本

标签 c# asp.net-mvc html-helper

我正在尝试制作一个 HTML 帮助器,它允许使用 using 中的任何文本,而不是将其写入最终页面。

Razor :

<div>
    <p>
        Before Inline
    </p>

    @using (Html.IncludeInlineScript("testScript"))
    {
        <script type="text/javascript">
            alert("hello world");
        </script>
    }

    <p>
        After Inline
    </p>
</div>

生成的 HTML:

<div>
    <p>
        Before Inline
    </p>

        <script type="text/javascript">
            alert("hello world");
        </script>
<!-- Top of Dispose -->
<!-- Bottom of Dispose -->

    <p>
        After Inline
    </p>
</div>

助手扩展方法:

public static ScriptWrapper IncludeInlineScript(this HtmlHelper helper, string scriptName)
{
    return new ScriptWrapper(helper);
}

包装器:

public class ScriptWrapper : IDisposable
{
    private HtmlHelper _helper;
    private TextWriter _originalWriter;
    private StringBuilder _scriptContents;

    public ScriptWrapper(HtmlHelper helper)
    {
        _helper = helper;
        _originalWriter = _helper.ViewContext.Writer;

        _scriptContents = new StringBuilder();
        _helper.ViewContext.Writer = new StringWriter(_scriptContents);
    }

    public void Dispose()
    {
        _originalWriter.WriteLine("<!-- Top of Dispose -->");
        _helper.ViewContext.Writer.Flush();
        _helper.ViewContext.Writer = _originalWriter;
        _originalWriter.WriteLine("<!-- Bottom of Dispose -->");
    }
}

这里的问题是尽管设置了 ViewContext.Writer对于一个新的 TextWriter,它仍然在写给原来的作者。很明显,dispose 的调用顺序正确,因为 dispose 的顶部在脚本之后。在设置新写入器后进行调试时 <script> block 不在流中,但是在处理时 <script>现在包含在原作者中。

razor 引擎是否保留了 writer 的本地副本并忽略了它已被设置为不同实例的事实?这对我来说似乎是一个错误。

最佳答案

万一有人想变通,因为我很不耐烦,我找到了一种方法来完成这项工作。它不太理想,但可以解决问题。如果将 ScriptWrapper 修改为:

public class ScriptWrapper : IDisposable
{
    private HtmlHelper _helper;
    private string _originalString;
    private StringBuilder _sb;

    public ScriptWrapper(HtmlHelper helper)
    {
        _helper = helper;
        _sb = ((StringWriter) _helper.ViewContext.Writer).GetStringBuilder();
        _originalString = _sb.ToString();
        _sb.Clear();
    }

    public void Dispose()
    {
        var contents = _sb.ToString();
        _sb.Clear();
        _sb.Append(_originalString);
    }
}

您可以在 using(...) 语句中使用任何内容来实现预期的结果。

不过,我仍然很想知道是否有一种方法可以在不破解这样的解决方案的情况下做到这一点。

关于c# - HtmlHelper 在使用中使用 html/文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39216018/

相关文章:

c# - PostBack 后在 GridView 中保留 DataSource

jquery - MVC + jQuery : how to create an input text through Html. TextBox() 并指定 "class"属性

c# - "Update.exe not found, not a Squirrel-installed app"错误中指定的 Update.exe 是什么?

c# - 数据表选择产生不正确的列连接

c# - 帮助 jQuery 投票系统。无法更新 html 投票计数

html - 网页右侧多余空格导致水平滚动条

c# - 将按钮的值从 ASP.NET MVC 3 Razor 页面传回 C# Controller

c# MVC Html helper + 表达式 + 去除丑陋

asp.net-mvc - 在自定义HTML帮助器中调用Html.ActionLink

C# SVG(使用 device-cmyk() 或 icc-color())到 PDF 转换