简体   繁体   English

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

[英]ASP.NET MVC - RuntimeBinderException when passing dynamic ExpandoObject from Controller to View

Since it is not possible to pass multiple models to a view in ASP.NET MVC 4, I am trying to stuff the various models into a dynamic ExpandoObject and then unpacking it from within the view. 由于无法将多个模型传递给ASP.NET MVC 4中的视图,因此我试图将各种模型填充到动态ExpandoObject ,然后从视图中解压缩它。

My Model (consists of more than just this class, but for brevity I'll just show this): 我的模型 (不仅仅包括此类,而且为简单起见,我将仅显示此模型):

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

My Controller: (I am packing more than just this List<> object into the dynamic object, but for brevity's sake...) 我的控制器:(我不仅将这个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;

My View: (This is the first thing in the view and the program chokes on the following assignment) 我的视图:(这是视图中的第一件事,程序在以下分配中令人窒息)

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

When the cursor reaches the above assignment in the View layer, it throws the following exception: 当光标到达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)}

Does anyone know what I need to do to fix this? 有谁知道我需要做些什么来解决这个问题? Not sure if it's a quick fix or a more extensive redesign. 不知道这是快速修复还是更广泛的重新设计。

You send list artist but try to get one artist you should change this 您发送列表艺术家,但尝试获取一位艺术家,则应更改此设置

string artist_Name = Model.Artist.Artist_Name;

To

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

Or 要么

Change 更改

@model dynamic

To

@model ExpendoObject

I think that using dynamic object is not a good idea,by default views are strongly typed and without Model there is no way to create attribute based model validation ... 我认为使用动态对象不是一个好主意,默认情况下视图是强类型的,没有模型就无法创建基于属性的模型验证...

By referring to the official documentation and others resources you can use extension method to convert your object into an ExpandoObject and your function should be works : 通过参考官方文档和其他资源,您可以使用扩展方法将您的对象转换为ExpandoObject,并且您的功能应该可以使用:

Extension method : 扩展方式:

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

In the return of your controller method try to add: 在您的控制器方法的返回中,尝试添加:

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

Explanation: 说明:

The reason for this is that the anonymous type being passed in the controller in internal, so it can only be accessed from within the assembly in which it's declared. 原因是匿名类型在内部的控制器中传递,因此只能从声明它的程序集中进行访问。 Since views get compiled separately, the dynamic binder complains that it can't go over that assembly boundary. 由于视图是分别编译的,因此动态活页夹抱怨它不能越过该程序集边界。

But if you think about it, this restriction from the dynamic binder is actually quite artificial, because if you use private reflection, nothing is stopping you from accessing those internal members (yes, it even work in Medium trust). 但是,如果您考虑一下,动态绑定器的这种限制实际上是很人为的,因为如果您使用私有反射,那么什么也不会阻止您访问这些内部成员(是的,它甚至在“中等信任”中也有效)。 So the default dynamic binder is going out of its way to enforce C# compilation rules (where you can't access internal members), instead of letting you do what the CLR runtime allows. 因此,默认的动态绑定程序将无法执行C#编译规则(您无法访问内部成员),而不是让您执行CLR运行时所允许的工作。

For more details please read this answer: 有关更多详细信息,请阅读以下答案:

Dynamic Anonymous type in Razor causes RuntimeBinderException Razor中的动态匿名类型导致RuntimeBinderException

and this article: 和这篇文章:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM