ASP.NET MVC-将动态ExpandoObject从控制器传递到视图时出现RuntimeBinderException

时间:2019-04-19 22:06:19

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

由于无法在ASP.NET MVC 4中将多个模型传递给视图,因此我试图将各种模型填充到动态ExpandoObject中,然后从视图中解压缩。

我的模型(不仅仅包括此类,但为简洁起见,我将仅显示该类):

public class Modular_ArtistModel
{
    public string Artist_Name { get; set; }
}

我的控制器: (我不只是将这个List<>对象包装到dynamic对象中,但是为了简洁起见...)

dynamic ArtistModel = new ExpandoObject();

        var Modular_ArtistModel = LoadSP_Modular_ArtistModel("sp_Mod_Artist_Artist", i);
        List<Modular_ArtistModel> mod_ArtistModel = new List<Modular_ArtistModel>();
        foreach (var row in Modular_ArtistModel)
        {
            mod_ArtistModel.Add(new Modular_ArtistModel
            {
                Artist_Name = row.Artist_Name
            });
        }
        ArtistModel.Artist = mod_ArtistModel;

我的视图: (这是视图中的第一件事,程序在以下分配中令人窒息)

@model dynamic
@{
string artist_Name = Model.Artist.Artist_Name;
}

当光标在View层中达到上述分配时,它将引发以下异常:

'Model.Artist.Artist_Name' threw an exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException'
Data: {System.Collections.ListDictionaryInternal}
HResult: -2146233088
HelpLink: null
InnerException: null
Message: "'System.Collections.Generic.List<....Models.Modular_ArtistModel>' does not contain a definition for 'Artist_Name'"
Source: "Anonymously Hosted DynamicMethods Assembly"
StackTrace: "   at CallSite.Target(Closure , CallSite , Object )\r\n   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)"
TargetSite: {System.Object CallSite.Target(System.Runtime.CompilerServices.Closure, System.Runtime.CompilerServices.CallSite, System.Object)}

有人知道我需要做什么来解决此问题吗?不知道这是快速修复还是更广泛的重新设计。

2 个答案:

答案 0 :(得分:1)

您发送了艺术家名单,但尝试让一位艺术家进行更改

string artist_Name = Model.Artist.Artist_Name;

收件人

string artist_Name= Model.Artist.FirstOrDefault().Artist_Name;

更改

@model dynamic

收件人

@model ExpendoObject

答案 1 :(得分:1)

我认为使用动态对象不是一个好主意,默认情况下,视图是强类型化的,没有Model,就无法创建基于属性的模型验证...

通过参考官方文档和其他资源,您可以使用扩展方法将您的对象转换为ExpandoObject,并且您的功能应该可以使用:

扩展方法:

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;
}

在返回控制器方法时,尝试添加:

return ( "yourView", ArtistModel.ToExpando() ); 

说明:

  

这样做的原因是匿名类型在内部控制器中传递,因此只能从声明它的程序集中进行访问。由于视图是分别编译的,因此动态活页夹抱怨它不能越过装配边界。

     

但是,如果您考虑一下,动态绑定器的这种限制实际上是很人为的,因为如果使用私有反射,那么什么也不会阻止您访问这些内部成员(是的,它甚至在“中等信任”中也有效)。因此,默认的动态绑定程序将不执行强制C#编译规则(您无法访问内部成员)的方式,而不是让您执行CLR运行时所允许的操作。

有关更多详细信息,请阅读以下答案:

Dynamic Anonymous type in Razor causes RuntimeBinderException

和本文

https://blogs.msdn.microsoft.com/davidebb/2009/12/18/passing-anonymous-objects-to-mvc-views-and-accessing-them-using-dynamic/