MVC 3 Html.DisplayFor(...)代码不生成HTML代码

时间:2014-11-07 16:40:11

标签: c# html asp.net-mvc asp.net-mvc-3

我正在使用MVC 3中的通用详细信息页面,在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是格式为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)的代码。问题解决了。

2 个答案:

答案 0 :(得分:2)

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 *@

UIHint用法

你的模型被装饰(但保留类型):

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

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

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

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

答案 1 :(得分:2)

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

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

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

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

然后在MyCustomHyperlink.cshtml

中创建一个名为/Views/Shared/DisplayTemlpates的部分
@model string
@if (!string.IsNullOrEmpty(model)) {
    <a href="@model" target=\"_blank\">@model</a>                  
}
else {
    <b>no url</b>
}