在视图中访问动态匿名类型时的RuntimeBinderException

Kab*_*lah 5 c# asp.net-mvc dynamic anonymous-types asp.net-mvc-3

我在学习/修补asp.net时遇到了一个奇怪的异常现象.

我试图显示这样的局部视图:

@Html.Partial("_PartialView", new { Action = "Foo" })
Run Code Online (Sandbox Code Playgroud)

当我尝试访问Action时

// Throws Microsoft.Csharp.RuntimeBinder.RuntimeBinderException
string throwsException = Model.Action; 
Run Code Online (Sandbox Code Playgroud)

带有消息的RuntimeBinderExceptionis

'object'不包含'Action'的定义

被扔了.
奇怪的是这条线很好用:

// This line works fine
string works = ((Type)Model.GetType()).GetProperty("Action").GetValue(Model);
Run Code Online (Sandbox Code Playgroud)

这种行为让我很困惑,我宁愿避免使用这种解决方法.此外,我不认为问题是匿名类型是内部的,因为VS2013中ASP.NET项目的MVC模板成功完成了此操作:

在此输入图像描述

那么这里发生了什么?

Pau*_*aul 7

这个问题的答案可以在这里找到:http://www.heartysoft.com/ashic/blog/2010/5/anonymous-types-c-sharp-4-dynamic

从优秀的博客文章中拉出来:

Anonymous Types are Internal

调用Model.Action失败的原因是类型信息Model在运行时不可用.它不可用的原因是因为匿名类型不公开.当该方法返回该匿名类型的实例时,它返回一个System.Object,它引用一个匿名类型的实例 - 一个类型的信息不可用于主程序.动态运行时尝试查找Action在对象上调用的属性,但无法从其具有的类型信息中解析它.因此,它会引发异常.

  • 为什么VS2013 MVC模板可以工作呢?请参阅我的问题中的屏幕截图. (2认同)

Dar*_*rov 3

那么这里发生了什么?

您的部分视图是弱类型的。你没有@model它的定义。所以默认情况下它object显然没有属性Action

解决这个问题的正确方法是定义视图模型:

public class MyViewModel
{
    public string Action { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

您的部分视图将被强类型化为:

@model MyViewModel
@{
    string throwsException = Model.Action; 
}
Run Code Online (Sandbox Code Playgroud)

并将由主视图传递:

@Html.Partial("_PartialView", new MyViewModel { Action = "Foo" })
Run Code Online (Sandbox Code Playgroud)

另一种可能性(我个人不喜欢它,因为它依赖于运行时绑定)是在部分视图中使用动态模型:

@model dynamic
@{
    string throwsException = Model.Action; 
}
Run Code Online (Sandbox Code Playgroud)

然后你就可以在调用它时传递一个匿名对象:

@Html.Partial("_PartialView", new { Action = "Foo" })
Run Code Online (Sandbox Code Playgroud)