在重复的动态类型局部视图中从匿名类型 属性 发出 HTML 字符串
Emitting an HTML string from anonymous type property in a repeated, dynamically-typed Partial View
我将匿名类型作为 @model
的一部分传递到动态局部视图中,其中一个属性是包含一些 HTML 的字符串。当我使用 HtmlHelper
方法呈现 属性 时,Razor 引擎正在对字符串进行编码,从而在页面上生成文字文本 - 在本例中为 <i>text</i>
,而不是所需的 text
.
因为它是一个动态类型的View,我不能直接调用属性。具体来说,如果我尝试绑定到 @Model.MyField
,我会得到 RuntimeBindingException
:
'object' does not contain a definition for 'MyField'
理想情况下,我可以创建一个类型(或至少一个接口)来指定视图(我建议将其作为最佳解决方案),但我的工作范围不允许这样做。另外,我首先使用 Partial View
以便我可以为不同类型回收模板,这些类型具有相同的 属性 名称但这些属性的类型不同(耶遗留代码!) .
我查看了几个解决类似问题的相关问题,但答案不适用于我的具体情况(因为需要将匿名类型传递到我的 @model dynamic
视图)。
Displaying HTML String from Model in MVC Razor View
- 列出了几个失败的方法,决定通过
@(new HtmlString(stringWithMarkup))
或 MvcHtmlString.Create(stringWithMarkup)
创建一个 IHtmlString
- 两者都需要已知类型或局部变量,并且不适用于绑定匿名
object
的 属性
ASP.NET MVC4 - display HTML containing string as raw HTML
- 接受的答案有助于解释正在发生的事情:
All the output from helpers and other elements in Razor are put through HttpUtility.HtmlEncode, unless they implement IHtmlString
.
尝试过的解决方案
好吧,所以我假设我只是将我的 String
属性换成其中一个 IHtmlString
属性……不。因为我有匿名类型,Razor 引擎不知道 MyField
是一个 IHtmlString
,并且(我假设)调用 .ToString()
,然后像往常一样编码。
好吧,也许 @Html.DisplayFor
更聪明?是,但访问被拒绝:
'System.Web.Mvc.HtmlHelper' has no applicable method named 'DisplayFor' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
哦,对了。动态调度——我不能在匿名方法上调用扩展方法,因为 Razor 不知道它们是什么。因为我使用 @model dynamic
明确地告诉它,绝地风格,“你不需要看到它的标识”。如果我总是知道它是什么类型,那么是的,我可以在不使用语法的情况下转换对象或调用扩展方法——但同样,dynamic
和 anonymous
。这里有点鸡生蛋还是蛋生鸡的问题。
我发现/编译了两个解决方案,但我对这两个都不满意。 YMMV:
在渲染每个 Partial View
.
之前在父 View
中设置 ViewBag.MyField
好吧,我应该早点想出这个,但不得不提醒这种可能性 here 因为我很少使用它(尽可能使用强类型视图)。实际上我很早就尝试过这个,但是由于我多次渲染 Partial 的方式,它似乎并不合适。我实际上仍然不喜欢它,因为在父视图中,我必须在每次调用 @Html.Partial
之前不断更新 ViewBag.MyField
(我的用例为 6 次)。这将 C# 代码 和 变量重用放置在我内容中间的页面下方,很容易遗漏并且难以维护。
使用反射:object myField = ((Type)Model.GetType()).GetProperty("MyField").GetValue(Model);
这就是我最终决定用于我的用例的内容。尽管反射 wasn't intended for this scenario,尽管它需要一些额外的错误检查。维护它的人比 .NET MVC 更熟悉反射,它将代码合并到一个位置 - 在它重要的页面上,以及其余 "server-side" 操作的顶部。没有重复的电话或寻找参考。
我实际上并不完全清楚为什么这有效(也适用于 dynamic
而不是 object
),但我假设它与正在检查的 Razor 引擎有关myField
对象类型直接用于已知类型 (IHtmlString
) 的特殊呈现,而不是看到未知的 object
并需要访问未知存在的 属性在编译时。
我将匿名类型作为 @model
的一部分传递到动态局部视图中,其中一个属性是包含一些 HTML 的字符串。当我使用 HtmlHelper
方法呈现 属性 时,Razor 引擎正在对字符串进行编码,从而在页面上生成文字文本 - 在本例中为 <i>text</i>
,而不是所需的 text
.
因为它是一个动态类型的View,我不能直接调用属性。具体来说,如果我尝试绑定到 @Model.MyField
,我会得到 RuntimeBindingException
:
'object' does not contain a definition for 'MyField'
理想情况下,我可以创建一个类型(或至少一个接口)来指定视图(我建议将其作为最佳解决方案),但我的工作范围不允许这样做。另外,我首先使用 Partial View
以便我可以为不同类型回收模板,这些类型具有相同的 属性 名称但这些属性的类型不同(耶遗留代码!) .
我查看了几个解决类似问题的相关问题,但答案不适用于我的具体情况(因为需要将匿名类型传递到我的 @model dynamic
视图)。
Displaying HTML String from Model in MVC Razor View
- 列出了几个失败的方法,决定通过
@(new HtmlString(stringWithMarkup))
或MvcHtmlString.Create(stringWithMarkup)
创建一个 - 两者都需要已知类型或局部变量,并且不适用于绑定匿名
object
的 属性
IHtmlString
- 列出了几个失败的方法,决定通过
ASP.NET MVC4 - display HTML containing string as raw HTML
- 接受的答案有助于解释正在发生的事情:
All the output from helpers and other elements in Razor are put through HttpUtility.HtmlEncode, unless they implement
IHtmlString
.
- 接受的答案有助于解释正在发生的事情:
尝试过的解决方案
好吧,所以我假设我只是将我的
String
属性换成其中一个IHtmlString
属性……不。因为我有匿名类型,Razor 引擎不知道MyField
是一个IHtmlString
,并且(我假设)调用.ToString()
,然后像往常一样编码。好吧,也许
@Html.DisplayFor
更聪明?是,但访问被拒绝:'System.Web.Mvc.HtmlHelper' has no applicable method named 'DisplayFor' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
哦,对了。动态调度——我不能在匿名方法上调用扩展方法,因为 Razor 不知道它们是什么。因为我使用
@model dynamic
明确地告诉它,绝地风格,“你不需要看到它的标识”。如果我总是知道它是什么类型,那么是的,我可以在不使用语法的情况下转换对象或调用扩展方法——但同样,dynamic
和anonymous
。这里有点鸡生蛋还是蛋生鸡的问题。
我发现/编译了两个解决方案,但我对这两个都不满意。 YMMV:
在渲染每个
之前在父Partial View
.View
中设置ViewBag.MyField
好吧,我应该早点想出这个,但不得不提醒这种可能性 here 因为我很少使用它(尽可能使用强类型视图)。实际上我很早就尝试过这个,但是由于我多次渲染 Partial 的方式,它似乎并不合适。我实际上仍然不喜欢它,因为在父视图中,我必须在每次调用
@Html.Partial
之前不断更新ViewBag.MyField
(我的用例为 6 次)。这将 C# 代码 和 变量重用放置在我内容中间的页面下方,很容易遗漏并且难以维护。使用反射:
object myField = ((Type)Model.GetType()).GetProperty("MyField").GetValue(Model);
这就是我最终决定用于我的用例的内容。尽管反射 wasn't intended for this scenario,尽管它需要一些额外的错误检查。维护它的人比 .NET MVC 更熟悉反射,它将代码合并到一个位置 - 在它重要的页面上,以及其余 "server-side" 操作的顶部。没有重复的电话或寻找参考。
我实际上并不完全清楚为什么这有效(也适用于
dynamic
而不是object
),但我假设它与正在检查的 Razor 引擎有关myField
对象类型直接用于已知类型 (IHtmlString
) 的特殊呈现,而不是看到未知的object
并需要访问未知存在的 属性在编译时。