ASP.NET MVC - RuntimeBinderException при передаче динамического ExpandoObject из контроллера в представление - PullRequest
0 голосов
/ 20 апреля 2019

Поскольку невозможно передать несколько моделей в представление в 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;

My View: (Это первое в представлении, и программа задыхается от следующего назначения)

@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 ]

1 голос
/ 20 апреля 2019

Я думаю, что использование динамического объекта не является хорошей идеей, по умолчанию представления строго типизированы, и без модели нет способа создать аттестацию на основе проверки модели ...

Ссылаясь на официальную документацию и другие ресурсы, вы можете использовать метод расширения для преобразования вашего объекта в 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.

Для более подробной информации, пожалуйста, прочитайте этот ответ:

Динамический анонимный тип в Razor вызывает RuntimeBinderException

и эта статья:

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

1 голос
/ 20 апреля 2019

Вы отправляете список исполнителей, но пытаетесь найти одного исполнителя, вам нужно изменить это

string artist_Name = Model.Artist.Artist_Name;

На

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

Или

Изменить

@model dynamic

К

@model ExpendoObject
...