从发光匿名类型属性的HTML字符串中的重复,动态类型管窥 [英] Emitting an HTML string from anonymous type property in a repeated, dynamically-typed Partial View

查看:182
本文介绍了从发光匿名类型属性的HTML字符串中的重复,动态类型管窥的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我传递一个匿名类型转换为动态的局部视图为包含一些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




试图解决方案


  1. 好吧,所以我想我就换我的字符串属性出其中的一个 IHtmlString 属性...都能跟得上。因为我有匿名类型,剃刀引擎不知道 MyField的 IHtmlString ,和(我认为)电话的ToString(),然后将其连接codeD和往常一样。


  2. 好吧,也许 @ Html.DisplayFor 是聪明吗?是的,但访问被拒绝:


      

    System.Web.Mvc.HtmlHelper'中有一个名为没有适用的方法DisplayFor,但似乎有这个名字的扩展方法。扩展方法不能进行动态调度。考虑强制转换动态参数或调用没有扩展方法的语法扩展方法。


    哦,对了。动态分派 - 我不能调用匿名方法扩展方法,因为剃刀不知道它们是什么。因为我使用 @model动态来明确告诉它,绝地式的你并不需要看它的标识的。如果我一直都知道这是什么类型的,那么是的,我可以投的对象或调用扩展方法,而无需使用语法 - 但同样,动态匿名。排序这里是一个鸡和蛋的问题。



解决方案

我发现/编译两种解决方案,这两者都不是我真的开心。因人而异:


  1. 设置 ViewBag.MyField 查看渲染前各局部视图

    好吧,我想通这一个了很多越快,但必须得到这里因为提醒这种可能性的我很少使用它(preferring强类型的意见尽可能)。其实我也尝试这种早,但由于办法,我渲染局部多次,似乎没有什么是适当的。其实我还是不喜欢它,因为在父母看来,我必须保持更新 ViewBag.MyField 每次调用 @ Html.Partial <前/ code>(我用例6倍)。这使得C#code的的变量重用的方式倒在我的内容,在这里很容易错过,难以维持的中间页。


  2. 使用反射:对象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)) or MvcHtmlString.Create(stringWithMarkup)
    • Both of which require a known type or local variable, and don't work for binding a property of an anonymous object
  • 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.

Attempted solutions

  1. Okay, so I assume I'll just swap my String properties out for one of those IHtmlString properties... nope. Since I have anonymous type, the Razor engine doesn't know that MyField is an IHtmlString, and (I assume) calls .ToString(), which is then encoded as usual.

  2. 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 and anonymous. Sort of a chicken and egg issue here.

解决方案

I found / compiled two solutions, neither of which am I really happy with. YMMV:

  1. Set ViewBag.MyField in the parent View before rendering each Partial 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.

  2. 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 of object), but I'm assuming it's something to do with the Razor engine is inspecting the myField object type directly for special rendering of a known type (IHtmlString), rather than seeing an unknown object and needing to access a property that is not known to exist at compile time.

这篇关于从发光匿名类型属性的HTML字符串中的重复,动态类型管窥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆