从发光匿名类型属性的HTML字符串中的重复,动态类型管窥 [英] Emitting an HTML string from anonymous type property in a repeated, dynamically-typed Partial View
问题描述
我传递一个匿名类型转换为动态的局部视图为包含一些HTML的 @model
和属性之一是字符串的一部分。当我使用的HtmlHelper
方法来呈现属性,剃刀引擎编码字符串,从而在页面上的文字文本 - < I>文字< / I>
在这种情况下,而不是所期望的 文本
的
由于它是一个动态类型的看法,我不能直接调用该属性。特别是,如果我尝试绑定到 @ Model.MyField
,我收到了 RuntimeBindingException
:
'对象'不包含'MyField的的定义
理想我可以创建一个类型(或至少一个接口)指定的观点(我推荐的最佳解决方案),但我的工作范围不允许这样。再加上我使用摆在首位的部分查看
,这样我可以回收为不同类型,具有相同的属性名称,但不是同一类型的这些属性模板(耶传统code!)。
我已经看过了解决类似问题的几个相关的问题,但答案没有为我的特殊环境下进行(由于需要匿名类型传递给我的 @model动态
视图))。
-
从模型的MVC剃刀视图显示HTML字符串
- 列出了几个失败的方法,办结上创建一个
IHtmlString
通过@(新HtmlString(stringWithMarkup))
或MvcHtmlString.Create(stringWithMarkup)
- 这两者都需要一个已知类型或局部变量,不绑定一个匿名
对象的属性工作
- 列出了几个失败的方法,办结上创建一个
-
ASP.NET MVC4 - 包含字符串显示HTML原始的HTML
- 接受的答案可以帮助解释了发生的事情:
所有的助手和其他元素在剃刀输出通过HttpUtility.HtmlEn code放,除非他们实施
IHtmlString
。
块引用>
- 接受的答案可以帮助解释了发生的事情:
试图解决方案
-
好吧,所以我想我就换我的
字符串
属性出其中的一个IHtmlString
属性...都能跟得上。因为我有匿名类型,剃刀引擎不知道MyField的
是IHtmlString
,和(我认为)电话的ToString()
,然后将其连接codeD和往常一样。 -
好吧,也许
@ Html.DisplayFor
是聪明吗?是的,但访问被拒绝:
System.Web.Mvc.HtmlHelper'中有一个名为没有适用的方法DisplayFor,但似乎有这个名字的扩展方法。扩展方法不能进行动态调度。考虑强制转换动态参数或调用没有扩展方法的语法扩展方法。
块引用>哦,对了。动态分派 - 我不能调用匿名方法扩展方法,因为剃刀不知道它们是什么。因为我使用
@model动态
来明确告诉它,绝地式的你并不需要看它的标识的。如果我一直都知道这是什么类型的,那么是的,我可以投的对象或调用扩展方法,而无需使用语法 - 但同样,动态
和匿名
。排序这里是一个鸡和蛋的问题。
我发现/编译两种解决方案,这两者都不是我真的开心。因人而异:
-
设置
ViewBag.MyField
父查看
渲染前各局部视图
。好吧,我想通这一个了很多越快,但必须得到这里因为提醒这种可能性的我很少使用它(preferring强类型的意见尽可能)。其实我也尝试这种早,但由于办法,我渲染局部多次,似乎没有什么是适当的。其实我还是不喜欢它,因为在父母看来,我必须保持更新
ViewBag.MyField
每次调用@ Html.Partial <前/ code>(我用例6倍)。这使得C#code的和的变量重用的方式倒在我的内容,在这里很容易错过,难以维持的中间页。
-
使用反射:
对象MyField的=((类型)Model.GetType())的getProperty(MyField的)的GetValue(模型);
这是最终我决定去我的用例。即使反射的目的不是为这种情况,即使这需要一点点额外的错误检查。谁将会保持这种情况的人都比较熟悉的莫过于.NET MVC反映,它整合了code到一个地方 - 它关系到页面上,并在与服务器端的其余部分顶部操作。无重复来电或追捕引用。
实际上,我为什么这工作还不完全清楚(还与一个
动态
而不是对象
) ,但我假设它的东西做的剃刀引擎直接已知类型的特殊渲染(IHtmlString <检查
MyField的
对象类型/ code>),而不是看到一个未知对象
和需要访问不知道在编译时存在的属性。
I am passing an anonymous type into a dynamic partial view as part of the @model
, and one of the properties is a string that contains some HTML. When I use the HtmlHelper
methods to render the property, the Razor engine is encoding the string, resulting in literal text on the page - <i>text</i>
in this case, instead of the desired text
.
Since it is a dynamically typed View, I cannot call the property directly. Specifically, if I try to bind to @Model.MyField
, I get a RuntimeBindingException
:
'object' does not contain a definition for 'MyField'
Ideally I could create a type (or at least an interface) to specify for the view (which I recommend as the optimal solution), but my scope of work does not permit this. Plus I'm using the Partial View
in the first place so that I can recycle the template for different types, which have the same property names but not the same type for those properties (yay legacy code!).
I have looked at several related questions that address similar issues, but the answers do not work for my specific situation (due to needing the anonymous type passed to my @model dynamic
view)).
Displaying HTML String from Model in MVC Razor View
- Lists several failed approaches, settles on creating an
IHtmlString
via@(new HtmlString(stringWithMarkup))
orMvcHtmlString.Create(stringWithMarkup)
- Both of which require a known type or local variable, and don't work for binding a property of an anonymous
object
- Lists several failed approaches, settles on creating an
ASP.NET MVC4 - display HTML containing string as raw HTML
- Accepted answer helps explains what's happening:
All the output from helpers and other elements in Razor are put through HttpUtility.HtmlEncode, unless they implement
IHtmlString
.
- Accepted answer helps explains what's happening:
Attempted solutions
Okay, so I assume I'll just swap my
String
properties out for one of thoseIHtmlString
properties... nope. Since I have anonymous type, the Razor engine doesn't know thatMyField
is anIHtmlString
, and (I assume) calls.ToString()
, which is then encoded as usual.Alright, maybe
@Html.DisplayFor
is smarter? Yes, but access is denied:'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.
Oh, right. Dynamically dispatched - I can't call extension methods on anonymous methods, because Razor doesn't know what they are. Because I'm using
@model dynamic
to explicitly tell it, Jedi-style, "You don't need to see its identification". If I always knew what type it was, then yes, I could cast the object or call the extension method without using the syntax - but again,dynamic
andanonymous
. Sort of a chicken and egg issue here.
I found / compiled two solutions, neither of which am I really happy with. YMMV:
Set
ViewBag.MyField
in the parentView
before rendering eachPartial View
.Okay, I should have figured this one out a lot sooner, but had to get reminded of this possibility here because I rarely use it (preferring strongly-typed views whenever possible). I actually did try this early on, but due to the way I'm rendering the Partial multiple times it didn't seem to be appropriate. I actually still don't like it because in the parent view, I have to keep updating
ViewBag.MyField
before every call to@Html.Partial
(6 times for my use case). This puts C# code and variable reuse way down the page in the middle of my content, where it is easy to miss and hard to maintain.Use reflection:
object myField = ((Type)Model.GetType()).GetProperty("MyField").GetValue(Model);
This is ultimately what I decided to go with for my use case. Even though reflection wasn't intended for this scenario, even though it requires a little extra error checking. The people who will be maintaining this are more familiar with reflection than .NET MVC, and it consolidates the code into one spot - on the page that it matters to, and at the top with the rest of the "server-side" manipulations. No repeated calls or hunting down references.
I'm actually not entirely clear on why this works (also works with a
dynamic
instead ofobject
), but I'm assuming it's something to do with the Razor engine is inspecting themyField
object type directly for special rendering of a known type (IHtmlString
), rather than seeing an unknownobject
and needing to access a property that is not known to exist at compile time.
这篇关于从发光匿名类型属性的HTML字符串中的重复,动态类型管窥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!