【问题标题】:MVC Razor: Helper method to render alternate content when emptyMVC Razor:空时呈现替代内容的辅助方法
【发布时间】:2013-03-01 14:57:59
【问题描述】:

我有一些数据,有时这些数据是空白的。我宁愿使用一个辅助方法来渲染数据(如果存在),并在字符串为空/null时渲染一些仅显示“N/A”的HTML,而不是在我的视图上制作一堆疯狂的逻辑。

理想语法:@Helpers.RenderThisOrThat(Model.CustomerPhone)

如果Model.CustomerPhone(一个字符串)为空,它将呈现这个替代的HTML:<span class='muted'>N/A</span>

这是我们目前所拥有的:

@helper RenderThisOrThat(string stringToRender, string methodToGetAlternateText = null)
{
    @RenderThisOrThat(MvcHtmlString.Create(stringToRender), methodToGetAlternateText)
}

@helper RenderThisOrThat(MvcHtmlString stringToRender, string methodToGetAlternateText = null)
{
    if (string.IsNullOrWhiteSpace(stringToRender.ToHtmlString()))
    {
        if (!string.IsNullOrWhiteSpace(methodToGetAlternateText)) {
            @methodToGetAlternateText
        }

        <span class='muted'>N/A</span>
    }

    @stringToRender
}

这工作得很好,直到我们想要将字符串以外的东西传递给任一参数。例如,当我们有一个电子邮件地址时,我们希望它是该电子邮件的链接,而不仅仅是电子邮件的字符串。

@Helpers.RenderThisOrThat(@&lt;a href="mailto:@Html.DisplayFor(m =&gt; m.CustomerEmail)"&gt;@Html.DisplayFor(m =&gt; m.CustomerEmail)&lt;/a&gt;)

它给了我们错误:“无法将 lambda 表达式转换为类型'字符串',因为它不是委托类型”

我们不知道如何进行这项工作......这里有什么帮助吗?

【问题讨论】:

  • 你能写出这样的代码吗?除了您的辅助方法之外,我认为 Razor 无法解释这一点
  • 您引用的是System.Linq; 吗?
  • @Kami LINQ 是做什么用的?
  • 创建一个接受 lambda @Helper TextEditorBlock(&lt;Expression&lt;Func&lt;Product, string&gt;&gt; expression)的方法覆盖

标签: asp.net-mvc razor


【解决方案1】:

您正在寻找一个可以接受字符串的助手,并且:

  1. 如果字符串不为空,则呈现该字符串。
  2. 如果字符串不为空,则呈现给定的模板。
  3. 如果字符串为空,则呈现“N/A”html。
  4. 如果字符串为空,则呈现给定模板。

当将 razor 块作为参数传递给函数时,razor 将该块打包为 Func。更改辅助函数中的参数以采用该类型的委托,并且不要忘记调用这些委托(我选择传递 null)。

这些助手应该处理这些场景。

解决方案

@helper RenderThisOrThat(string stringToRender, Func<object, IHtmlString> leftTemplate = null, Func<object, IHtmlString> rightTemplate = null)
{
    var shouldRenderLeft = !string.IsNullOrWhiteSpace(stringToRender);
    leftTemplate = leftTemplate ?? (o => MvcHtmlString.Create(stringToRender));
    @RenderThisOrThat(shouldRenderLeft, leftTemplate, rightTemplate)
}

@helper RenderThisOrThat(bool shouldRenderLeft, Func<object, IHtmlString> leftTemplate, Func<object, IHtmlString> rightTemplate = null)
{
    var shouldRenderRight = !shouldRenderLeft;
    if (shouldRenderRight)
    {
        if (rightTemplate != null)
        {
            @rightTemplate(null)
        }
        else
        {
            <span class='muted'>N/A</span>
        }
    }
    else
    {
        @leftTemplate(null)
    }
}

示例

1. @Helpers.RenderThisOrThat(Model.StringWithBob)
2. @Helpers.RenderThisOrThat(Model.StringWithNull)
3. @Helpers.RenderThisOrThat(Model.StringWithBob, @<span>I'm @Model.StringWithBob</span>)
4. @Helpers.RenderThisOrThat(Model.StringWithNull, @<span>I'm @Model.StringWithBob</span>)
5. @Helpers.RenderThisOrThat(Model.StringWithBob, @<span>I'm @Model.StringWithBob</span>, @<span>What about Bob?</span>)
6. @Helpers.RenderThisOrThat(Model.StringWithNull, @<span>I'm @Model.StringWithBob</span>, @<span>What about Bob?</span>)

将输出:

  1. Bob
  2. &lt;span class='muted'&gt;N/A&lt;/span&gt;
  3. &lt;span&gt;I'm Bob&lt;/span&gt;
  4. &lt;span class='muted'&gt;N/A&lt;/span&gt;
  5. &lt;span&gt;I'm Bob&lt;/span&gt;
  6. &lt;span&gt;What about Bob?&lt;/span&gt;

【讨论】:

  • 这太棒了!另外,既然你是我的同事,我所要做的就是接受这个答案,然后hg pull
【解决方案2】:

对于一个简单的问题,这是一个非常复杂的解决方案。您不需要创建复杂的视图,事实上,您应该使用 Editor/DisplayTemplate,然后将您的逻辑放入模板中并完成一次,无需额外包含辅助函数或其他任何东西。

您还可以在此处更进一步,因为在这种情况下您将呈现一个电子邮件地址。您将 DataType 属性应用于模型,然后指定电话号码呈现类型。

public class MyModel {
    [DataType(DataType.PhoneNumber)]
    public string PhoneNumber {get;set;}
}

然后您在 ~/Views/Shared 中创建一个名为 DisplayTemplates 的文件夹,并在该文件夹中创建一个名为 PhoneNumber.cshtml 的文件,您可以在其中执行以下操作:

@model string

@if (string.IsEmptyOrWhiteSpace(Model)) {
    @:<span class='muted'>N/A</span>
} else {
   @: <span>@Model</span>
}

那么,在你看来:

@Html.DisplayFor(x => x.PhoneNumber)

就是这样,您认为没有复杂的逻辑,到处都没有卷积的辅助函数。这是简单、容易和可维护的。您可以对电子邮件地址执行相同的操作,因为电子邮件地址数据类型也是如此。

MVC 内置了很多非常好的功能,大多数人根本不使用,因为他们没有花任何时间真正学习它。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多