在MVC中使用动态匿名对象的RuntimeBinderException

时间:2011-05-02 14:04:40

标签: c# asp.net-mvc-3 dynamic

代码

我有一个MVC项目的部分页面看起来像这样:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<div class="tab-window <%= Model.TargetClass %> <%= Model.TargetTab == Model.SelectedTab ? "selected" : "" %>"
    data-window-url="/SomeUrl/Partial/<%= Model.TargetTab %>/"
    <%= Model.TargetTab == Model.SelectedTab ? "data-content-loaded=\"true\"" : "" %>>
    <% if (Model.TargetTab == Model.SelectedTab) {
           Html.RenderPartial(Model.TargetTab as string, Model.Model as object);
        } %>
</div>

它的作用是打开另一个部分(在Model.TargetTab中命名的)Model.Model,如果它是当前可见的选项卡,否则只渲染一个空div(加载了jQuery)需要时。)

它的名字是这样的:

<% Html.RenderPartial("TabWindowContainer", new { TargetTab = "MyTabName", TargetClass = "my-tab-class", SelectedTab = Model.Tab, Model = Model }); %>

这曾经有效。

然后我更改了Model中的值,它停止了工作。我改回来了,它还没有用。需要说明的是,hg状态目前不显示任何这些文件。

例外

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'object' does not contain a definition for 'TargetClass'

当您尝试在“快速监视”窗口中打开Model时,您会看到它已使用正确的值设置了所有属性

Quickwatch

但是当你试图查看任何属性时,你会得到与之前相同的异常

Quickwatch with exception

想到这一点,我意识到这可能根本不起作用;我们尝试访问的对象来自不同的程序集,因此我们无法查看其属性。但是,为什么它用于工作?我还有一个正在运行的版本。我该怎么做才能让它再次发挥作用?

更新:应该工作;模型来自同一装配体中的另一个视图,而不是来自控制器。

1 个答案:

答案 0 :(得分:8)

您的动态类型无法在匿名类型中找到属性,因为匿名类型的属性是内部属性(非公共属性)。因此,即使调试器明显看到匿名类型的属性,您的应用程序也会抛出异常。 Reference.

创建一个Expando扩展方法。

public static ExpandoObject ToExpando(this object anonymousObject)
            {
                IDictionary<string, object> anonymousDictionary = new RouteValueDictionary(anonymousObject);
                IDictionary<string, object> expando = new ExpandoObject();
                foreach (var item in anonymousDictionary)
                    expando.Add(item);
                return (ExpandoObject)expando;
            }

如此应用扩展程序。

<% Html.RenderPartial("TabWindowContainer", new { TargetTab = "MyTabName", TargetClass = "my-tab-class", SelectedTab = Model.Tab, Model = Model }.ToExpando()); %>

希望这会有效,我不会因为误解这个问题而使自己难堪。