MVC 3 Html.DisplayFor(..)代码未生成Html代码

本文关键字:代码 Html 未生 DisplayFor MVC | 更新日期: 2023-09-27 18:29:31

我正在MVC 3中开发一个通用的Details页面,它在View:中看起来像这样

<fieldset>
    <legend style="font-size:large">Info</legend>
    <div class="display-label">Url1:</div>
    <div class="display-field">
        @Html.DisplayFor(model => model.Url1)
    </div>
    <div class="display-label">Url2:</div>
    <div class="display-field">
        @Html.DisplayFor(model => model.Url2)
    </div>
<fieldset>

在模型中是这样的:

public HtmlString Url1
{
    get
    {
        if (!string.IsNullOrEmpty(Url1))
        {
            return new HtmlString("<a href='"" + Url1 
                                  + "'" target='"_blank'">" + Url1 + "</a>");
        }
        return new HtmlString("<b>no url</b>");
    }
}
public HtmlString Url2
{
    get
    {
        if (!string.IsNullOrEmpty(Url2))
        {
            return new HtmlString("<a href='"" + Url2
                                  + "'" target='"_blank'">" + Url2 + "</a>");
        }
        return new HtmlString("<b>no url</b>");
    }
}

Url1是一个url,格式为http://www.website.com,Url2的格式为www.website.org/file.aspx

当我调试代码时,Url1的HtmlString会正确显示,但Url2的HtmlString不会。生成的Html源看起来像:

<div class="display-label">Url1</div>
    <div class="display-field">
        <a href="http://www.website.org">website</a> <br/>
    </div>
<div class="display-label">Url2</div>
    <div class="display-field">
    </div>

以前有人遇到过这样的问题吗?如果有,你是如何解决的?

更新

更新代码以使用@Model.Url1而不是@Html.DisplayFor(Url1)。问题已解决。

MVC 3 Html.DisplayFor(..)代码未生成Html代码

DisplayFor帮助程序可以利用模型(及其属性)的DisplayTemplates。假设您正在将HTML填充到这些属性中,您只需要直接输出它们。但是,由于MVC对所有输出进行编码,因此还需要引入@Html.Raw()帮助程序。因此,类似以下内容:

@Html.Raw(Model.Url1)

然而,就模型使用而言,这对MVC来说并不是一个好的实践。我建议(如果您必须使用HTML)为您的属性类型使用IHtmlString接口(所以现在它直接使用@Model.Url1输出),或者制作一个自定义对象和显示模板(UIHintAttribute的好用例)。


IHtmlString示例:

class UrlViewModel : IHtmlString {
  private readonly String url;
  private UrlViewModel(String url) {
    this.url = url;
  }
  public String ToHtmlString(){
    if (String.IsNullOrEmpty(this.url)){
      return new HtmlString("<a ...>...</a>");
    }
    return new HtmlString("<b>...</b>");
  }
}

然后您的模型变为:

class MyViewModel {
  private String url1;
  private String url2;
  public MyViewModel(String url1, String url2){
    this.ur1l = url1;
    this.url2 = url2;
  }
  public UrlViewModel Url1 { get; set; }
  public UrlViewModel Url2 { get; set; }
}

最后你的观点:

@Html.Url1 @* MVC automatically recognized an IHtmlString *@
@Html.Url2 @* implementation and outputs without escaping *@

UI提示用法

你的模型得到了装饰(但保留了类型):

class MyViewModel {
  [UIHint("MyUrl")]
  public String Url1 { get; set; }
  [UIHint("MyUrl")]
  public String Url2 { get; set; }
}

此外,只需向模型提供URL(而不提供HTML)。然后,添加一个新的DisplayTemplate(~/Views/Shared/DisplayTemplates/MyUrl.cs.html):

@model String
@if (!String.IsNullOrEmpoty(Model)) {
  <a href="@Model" target="_blank">@Model</a>
} else{
  <b>No Url</b>
}

您可以继续使用@Html.DisplayFor(x => x.Url1)

DavidG是对的,你把UI代码放在你的模型中,这不是一件好事。

相反,您应该将URL保持为字符串,并使用UIHintAttribute来告诉MVC要使用哪个分部来显示数据。

[UIHint("MyCustomHyperlink")]
public string URL1 { get; set; }
[UIHint("MyCustomHyperlink")]
public string URL2 { get; set; }

然后在/Views/Shared/DisplayTemlpates 中创建一个名为MyCustomHyperlink.cshtml的部分

@model string
@if (!string.IsNullOrEmpty(model)) {
    <a href="@model" target='"_blank'">@model</a>                  
}
else {
    <b>no url</b>
}
相关文章: