2

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

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

如果Model.CustomerPhone(a string) 为空,它将呈现此替代 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(@<a href="mailto:@Html.DisplayFor(m => m.CustomerEmail)">@Html.DisplayFor(m => m.CustomerEmail)</a>)

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

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

4

2 回答 2

2

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

  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. <span class='muted'>N/A</span>
  3. <span>I'm Bob</span>
  4. <span class='muted'>N/A</span>
  5. <span>I'm Bob</span>
  6. <span>What about Bob?</span>
于 2013-03-01T20:02:03.223 回答
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)

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

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

于 2013-03-01T20:57:28.320 回答