【问题标题】:ASP.Net MVC3 - Pass razor markup as a parameterASP.Net MVC3 - 将剃刀标记作为参数传递
【发布时间】:2012-02-27 18:57:25
【问题描述】:

我有一个名为EditableArea 的助手,它为用户提供运行时可编辑的div(通过JS)。 EditableArea 助手检查 DB 中是否存在具有指定 ID 的可编辑区域(与 MVC 的 Area 无关),如果存在则呈现该区域的 HTML,否则显示指定为助手参数的默认标记:

@Html.EditableArea(someId, "<p>Click to edit contents</p>")

一切正常,但我想更改它,以便将默认标记指定为不是字符串,而是以剃刀语法指定,例如:

@using (Html.EditableArea(someId))
{
    <p>Click to edit contents</p>
}

或者类似的东西,比如@sections 在 MVC3 中的工作方式。

我怎样才能做到这一点?

我可以创建一个IDisposable,在其Dispose 中关闭TagBuilder 等,但是使用这种方法仍然会呈现标记(我可以清除Dispose() 中呈现的内容,但代码块会仍然不必要地运行,我想避免)。

是否有其他方法可以将剃刀块传递给助手,它可能会或可能不会实际呈现?

【问题讨论】:

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


    【解决方案1】:

    下面是一个示例,我通过传入模板 ID 和模板本身的 razor 样式语法来呈现 jQuery 模板标记:

    public static MvcHtmlString jQueryTmpl(this HtmlHelper htmlHelper, 
        string templateId, Func<object, HelperResult> template) 
    {
        return MvcHtmlString.Create("<script id=\"" + templateId + 
            "\" type=\"x-jquery-tmpl\">" + template.Invoke(null) + "</script>");
    }
    

    这将被调用

    @Html.jQueryTmpl("templateId", @<text>any type of valid razor syntax here</text>)
    

    基本上只需使用Func&lt;object, HelperResult&gt; 作为参数并使用template.Invoke(null)(必要时使用参数)来呈现它。显然,您可以跳过对.Invoke() 的调用,以避免呈现“默认”标记。

    【讨论】:

    • 它不起作用。函数调用中的&lt;text&gt;...&lt;/text&gt; 语法未被识别(无效的表达式术语'
    • 很好,现在可以使用了。根本不需要&lt;text&gt; 标签(@ 就足够了),除非剃刀标记实际上是没有任何标签的纯文本,否则只需@&lt;tag&gt; 就足够了。
    • &lt;text&gt; 标签是正确的。我倾向于使用它们,以防万一我更改模板中的内容 - 如果您愿意,可以在未来证明。
    • 为什么将 null 传递给模板函数?参数有什么作用?
    • 'IHtmlHelper' 不包含 'jQueryTmpl' 的定义,并且没有可访问的扩展方法 'jQueryTmpl' 接受类型为 'IHtmlHelper' 的第一个参数(您是否缺少using 指令或程序集引用?)没有 mvc 核心??
    【解决方案2】:

    只是为了扩展已接受的答案,因为我花了很长时间才解决类似的问题,这就是弹出的问题。我真正需要的是一个@helper,它可以接受剃须刀文本,因为模板应该包含相当多的代码。我玩了很长时间,试图使用我在网上找到的几个版本的@helper item(Func&lt;object, HelperResult&gt; input),但没有成功。因此,我采用了如下方法:

    namespace project.MvcHtmlHelpers
    {
        public static class HelperExtensions
        {
            public static MvcHtmlString RazorToMvcString(this HtmlHelper htmlHelper, Func<object, HelperResult> template)
            {
                return MvcHtmlString.Create(template.Invoke(null).ToString());
            }
        }
    }
    

    @project.MvcHtmlHelpers    
    @helper item(other input, MvcHtmlString content)
        {
            <div class="item">
                ...other stuff... 
                <div class="content">
                    @content
                </div>
            </div>
        }
    

    并通过

    @item(other input, @Html.RazorToMvcString(@<text>this is a test</text>))
    

    现在我可以将帮助模板用于 Razor 输入,但我也可以放入部分视图,这在某些时候很方便。由于我不是专家,可能会有更好的选择,但对我来说这似乎是一种灵活的方法。

    【讨论】:

      【解决方案3】:

      如果你想知道这是如何在 asp.net core 3.1 中实现的

      @{
          void TemplateFunc(Func<object, IHtmlContent> template)
          {
              <div>@template(null)</div>
          }
      }
      

      然后在标记中你可以使用它

      <div>
      @{TemplateFunc(@<div>123</div>);}
      </div>
      

      【讨论】:

        【解决方案4】:

        更进一步,可以将标记直接传递给助手,而无需扩展方法。

        @helper HelperWithChild(Func<object, HelperResult> renderChild)
        {
            <div class="wrapper">
                @renderChild(this)
            </div>
        }
        
        @HelperWithChild(@<h1>Hello</h1>)
        

        对于多行标记&lt;text&gt; 也是必需的:

        @HelperWithChild(@<text>
            @AnotherHelper()
        
            <h1>
                With more markup
            </h1>
        </text>)
        
        @helper AnotherHelper()
        {
            <p>
                Another helper
            </p>
        }
        

        虽然我不确定this 将如何与Model 一起发挥作用 - 我的助手只使用他们的参数。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-07-07
          • 1970-01-01
          • 2011-07-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多