什么是 MvcHtmlString,我应该什么时候使用它?
Posted
技术标签:
【中文标题】什么是 MvcHtmlString,我应该什么时候使用它?【英文标题】:What is an MvcHtmlString and when should I use it? 【发布时间】:2011-01-18 14:22:09 【问题描述】:MvchtmlString
的 documentation 并不是很有启发性:
表示不应再次编码的 HTML 编码字符串。
我不清楚这究竟意味着什么。似乎某些 HTML 帮助方法返回了一个 MvcHtmlString
,但我在网上看到的几个自定义帮助方法的示例只返回一个常规字符串。
问题:
什么是MvcHtmlString
?
我什么时候应该选择MvcHtmlString
而不是string
,反之亦然?为什么?
【问题讨论】:
我投票支持文档链接:D 这对我有好处。谢谢! 【参考方案1】:ASP.NET 4 引入了新的代码块语法<%: %>
。本质上,<%: foo %>
转换为 <%= HttpUtility.HtmlEncode(foo) %>
。该团队正试图让开发人员尽可能使用 <%: %>
而不是 <%= %>
来防止 XSS。
然而,这引入了一个问题,如果代码块已经对其结果进行了编码,<%: %>
语法将重新编码它。这可以通过引入 IHtmlString 接口(.NET 4 中的新接口)来解决。如果<%: foo() %>
中的foo() 返回一个IHtmlString,<%: %>
语法将不会对其进行重新编码。
MVC 2 的助手返回 MvcHtmlString,它在 ASP.NET 4 上实现了接口 IHtmlString。因此,当开发者在 ASP.NET 4 中使用<%: Html.*() %>
时,结果不会被双重编码。
编辑:
这种新语法的直接好处是您的视图更清晰。例如,您可以写成<%: ViewData["anything"] %>
而不是<%= Html.Encode(ViewData["anything"]) %>
。
【讨论】:
我要补充一点,MVC 2 是针对 .Net 3.5 而不是 4 编译的。这意味着MvcHtmlString
没有实现 IHtmlString
,因为它只存在于 4 中。<%:
语法必须 duck-type - 无论接口如何,它都会在 .ToString()
之前调用 .ToHtmlString()
。
我的立场是正确的——实际上MvcHtmlString.Create
方法检测IHtmlString
是否可用并动态创建返回的类以支持它:windowsitpro.com/article/net-framework/Encoding-and-Strings/…
跟进: MvcHtmlString 和 HtmlString 之间有没有有意义的区别?在阅读了上面链接的文档之后,我仍然不知道 MvcHtmlString 给了我什么 HtmlString 没有。
@flipdoubt - 没有有意义的区别。
两者之间有一个非常细微的区别。如果您向 MvcHtmlString 传递一个空字符串,MvcHtmlString 将在 ToString() 或 ToHtmlString() 中返回 String.Empty。不过,HtmlString 将继续返回 null。【参考方案2】:
这是一个较晚的答案,但如果有人阅读此问题正在使用 razor,您应该记住的是,默认情况下 razor 会编码所有内容,但是通过在您的 html 帮助程序中使用 MvcHtmlString
,您可以告诉 razor 它没有'不需要对其进行编码。
如果你想让 razor 不对字符串进行编码,请使用
@Html.Raw("<span>hi</span>")
反编译 Raw(),向我们展示了它将字符串包装在 HtmlString 中
public IHtmlString Raw(string value)
return new HtmlString(value);
"HtmlString 仅存在于 ASP.NET 4 中。
MvcHtmlString 是添加到 MVC 2 以支持 .NET 3.5 和 .NET 4 的兼容性 shim。现在 MVC 3 仅是 .NET 4,它可能是 MVC 2->3 的 HtmlString 的一个相当简单的子类为了源兼容性。" source
【讨论】:
【参考方案3】:如果您想制作自己的HtmlHelper
扩展,则可以很好地实际使用它。例如,我讨厌试图记住<link>
标签的语法,所以我创建了自己的扩展方法来制作<link>
标签:
<Extension()> _
Public Function CssBlock(ByVal html As HtmlHelper, ByVal src As String, ByVal Optional ByVal htmlAttributes As Object = Nothing) As MvcHtmlString
Dim tag = New TagBuilder("link")
tag.MergeAttribute("type", "text/css")
tag.MergeAttribute("rel", "stylesheet")
tag.MergeAttribute("href", src)
tag.MergeAttributes(New RouteValueDictionary(htmlAttributes))
Dim result = tag.ToString(TagRenderMode.Normal)
Return MvcHtmlString.Create(result)
End Function
我本可以从这个方法返回String
,但如果我有以下内容会中断:
<%: Html.CssBlock(Url.Content("~/sytles/mysite.css")) %>
对于MvcHtmlString
,使用<%: ... %>
或<%= ... %>
都可以正常工作。
【讨论】:
【参考方案4】:如果您想将原始 HTML 传递给 MVC 辅助方法并且您不希望辅助方法对 HTML 进行编码,则可以使用 MvcHtmlString
。
【讨论】:
嗯...我认为 HTML 辅助方法的全部意义在于对 HTML 进行编码。否则我会用 HTML 辅助方法做什么? 除此之外,我什么时候想从 HTML 帮助方法中返回MvcHtmlString
?
传递或返回。如果您的 HTML 助手生成预先转义的 HTML,并且您不希望其他任何人重新转义它,您可能希望返回一个。
好的,我认为这让我更接近了一点,但是(冒着被认为是聪明人的风险)我如何决定是否要让其他人重新逃脱它?让某人能够弄乱转义的html通常是好/坏的做法吗?我以前从未见过这样的构造。 “它就像一根绳子,但请不要触摸它……并不是说有什么东西阻止你触摸它,但我们希望你不要触摸它。”这是关于什么的?
重点是,与常规字符串不同的是,this 字符串已经被编码。因此,没有必要触摸它。以上是关于什么是 MvcHtmlString,我应该什么时候使用它?的主要内容,如果未能解决你的问题,请参考以下文章
什么是 [Serializable],我应该什么时候使用它?