我有一些数据,有时数据是空白的。我不是在我的视图中制作一堆疯狂的逻辑,而是使用一个帮助方法来呈现数据(如果它存在),并在字符串为空/ 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(@<a href="mailto:@Html.DisplayFor(m => m.CustomerEmail)">@Html.DisplayFor(m => m.CustomerEmail)</a>)
它给我们错误:“无法将lambda表达式转换为'string'类型,因为它不是委托类型”
我们对如何完成这项工作感到茫然......在这里有任何帮助吗?
答案 0 :(得分:2)
你正在寻找一个带字符串的助手:
当将剃刀块作为参数传递给函数时,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>)
将输出:
Bob
<span class='muted'>N/A</span>
<span>I'm Bob</span>
<span class='muted'>N/A</span>
<span>I'm Bob</span>
<span>What about Bob?</span>
答案 1 :(得分: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内置了许多非常好的功能,大多数人根本不使用,因为他们没有花时间学习它。