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)。问题已解决。
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>
}