Динамічна модель MVC Razor, 'object' не містить визначення для 'PropertyName'


106

Використання MVC 3 з двигуном подання Razor. У мене такий вигляд:

@model dynamic
@{
    var products = (List<ListItemBaseModel>)Model.Products;
    var threshold = (int)(Model.Threshold ?? 1);
    var id = Guid.NewGuid().ToString();
}

Він викликається з іншого представлення за допомогою цього коду:

@Html.Partial("PartialViewName", new { Products = Model, Threshold = 5 })

В обох видах перегляду, коли я налагоджую їх і переглядаю Model, схоже, він містить правильний об'єкт. Коли я виконую код, я отримую помилку в рядку "var products =":

'об’єкт' не містить визначення для 'Продукти'

Хтось може мені пояснити, чому я отримую цю помилку? Знову ж таки, коли я переглядаю об’єкт Model у режимі налагодження, він виглядає нормально (маючи 2 властивості: Продукти та Поріг)


Відповіді:


150

Ви передаєте екземпляр анонімного класу як модель перегляду? Я просто спробував це (модель динамічного перегляду в CSHTML) і отримав таку ж помилку, що і ваша при використанні анонімного класу, але це спрацювало чудово, якщо я створив названий клас. Я шукав, але ніде не бачив цього документально.

// error
return View(new { Foo = 1, Bar = "test" });

// worked
return View(new TestClass { Foo = 1, Bar = "test" });

РЕДАКТИКА №1:

За словами Девіда Еббо , ви не можете передати анонімний тип у динамічно набраний вид, оскільки анонімні типи складені як internal. Оскільки перегляд CSHTML складено в окрему збірку, він не може отримати доступ до властивостей анонімного типу.

ЗРІД №2:

Девід Еббо відредагував свою посаду з цим уточненням:

Примітка (22.12.2011): тепер, коли MVC 3 має пряму підтримку динаміки, наведена нижче техніка більше не потрібна. Ця публікація насправді і призвела до інтеграції функції в MVC!


1
Правку приємно знати. Я просто мав ту саму проблему і не розумів WTF там. Дякую за пояснення.
Янік Рошон

18
EDIT №2 припускає, що зараз (MVC> 3) можна зробити рядок, позначений "помилкою"? return View(new { Foo = 1, Bar = "test" });? Оскільки я використовую MVC 4 і все ще отримую "об'єкт не містить визначення для Foo"
спорт

@sports мене теж ... Ви знайшли вирішення? (поруч із ToExpandoодним)
Олексій

2
Тож тепер у 2018 році за допомогою ASP.NET Core 2.1 та Razor поглядів я знаходжу, що помилка в первісному питанні все ще мене кусає. Тож я не знаю, про що йдеться у виправлення MVC 3, оскільки це все ще здається порушеним.
Ендрю Арнотт

41

На .NET 4.0 типи анонімних можна легко перетворити на ExpandoObjects, і таким чином всі проблеми виправляються за рахунок накладних витрат на саме перетворення. Ознайомтесь тут


Будь ласка. Можливо, це вдарить M $, щоб зробити анонімні типи більш корисними
Adaptabi

Це стосується партій? У мене з’явилася помилка, що Партії неможливо динамічно розсилати ...
Джон Бубріскі

1
Які партії? Чи можете ви навести приклад?
Адаптабі

27

Це не має нічого спільного з анонімними типами, що мають внутрішні властивості

Цілком можливо передати анонімні типи від подання до часткового перегляду

Я зіткнувся з тією ж проблемою і сьогодні, і це було нічого спільного з проблемою передачі анонімних типів та властивих їм internalвластивостей.

Таким чином, стосовно питання про ОП, відповідь від @Lucas не має значення - навіть незважаючи на те, що вирішення буде працювати .

У питанні щодо ОП анонімний тип передається від погляду в складі X до часткового в складі X , тому проблема, що Девід Еббо окреслив властивості, які є внутрішніми для анонімних типів, не має жодного наслідку; типи, складені для перегляду, частковий і анонімний тип, містяться в одній збірці .

Отже, що викликає раптову невдачу анонімного типу з погляду на часткове?

Принаймні в моїй ситуації я виявив, що це пов'язано з тим, що інший вид у ПОДІЛЬНІЙ папці визначає тип моделі, який неможливо вирішити . Перегляди збираються під час виконання, і тому це мало б сенс, оскільки невдача під час виконання компіляції переглядів також означала б невдачу складати динамічні типи, а часткова просто отримала б object. Не відразу зрозуміло, що відбувається, але в конкретному прикладі ОП (і в моєму) це більш ніж ймовірно причина проблеми.

Цікаво зауважити, що якщо тип моделі правильний, але інша частина представлення не складається, то анонімні типи не впливають однаково. Це повинно зводитися до того, як Razor розбиває динамічну компіляцію на складові частини подання.

Після виправлення образливого вигляду або переобладнайте все рішення, або очистіть і відновіть проект, перш ніж перевірити, чи він виправлений.

Щоб переконатися, що вас це знову не зачепило, ви можете увімкнути компіляцію переглядів Razor за часом, додавши це у свій csprojфайл:

<PropertyGroup>
    <MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>

2
Це вирішило мою проблему - спочатку використання «@model динамики» здавалося правильним виправленням, але насправді відводило мене неправильним шляхом.
crimbo

Я очистив рішення, відновив його, і помилка зникла .. 121 голос проголошений.
maxbeaudoin

Я оновив свою відповідь, щоб відобразити підтримку MVC для моделей динамічного перегляду з MVC 3.
Лукас

Увімкнення періодичної компіляції переглядів завжди корисно для величезної бази кодів. Виявляє всілякі проблеми, друкарські помилки, помилки з T4MVC завдяки сильному набору тексту, запровадженого тощо.
Денис Грозний

О, правильно: я щойно помітив, що ми говоримо про перехід від погляду до часткового тут. Не від контролера до перегляду, що є моєю проблемою.
mwardm

9

Додайте наступний клас де завгодно у своєму рішенні (використовуйте Простір імен системи, щоб він був готовий до використання без додавання посилань) -

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

        }
    }

Коли ви відправляєте модель на перегляд, перетворіть її в Expando:

    return View(new {x=4, y=6}.ToExpando());

1
мені здається непотрібним накладними витратами, щоб спершу створити динамічний об’єкт, а потім створити ExpandoObject ... Просто замість цього створіть ExpandoObject ..
Baz1nga

@ Baz1nga Ви не можете зробити ... новий Expando () {prop = value, ...}, що робить це проблематичним. Я використовую JObject Json.Net для подібного використання.
Tracker1

3
Неправильно розміщувати HtmlHelper там ... публічний статичний ExpandoObject ToExpando (цей об'єкт o) {IDictionary <string, object> extendo = new ExpandoObject (); foreach (var propertyInfo in o.GetType (). GetProperties ()) {extendo.Add (новий KeyValuePair <рядок, об'єкт> (propertyInfo.Name, propertyInfo.GetValue (o, індекс: null))); } повернути (ExpandoObject) експандо; }
erlando

6

Замість використання dynamicтипу Модель в частковому поданні.

Ви можете викликати анонімні атрибути об'єкта, використовуючи @ViewData.Eval("foo")замість @Model.foo.

Потім ви можете видалити його @Model dynamicз подання.

Я нещодавно зіткнувся з цим питанням, коли передав деякі атрибути між поглядами на інтеграцію соціальних коментарів у Facebook. Приклад коду:

Html.RenderPartial(@"Layouts/Partials/_Comments", new {currentUrl = Model.CurrentPage.GetAbsoluteUrl(), commentCount = 5 });

Тоді, на мій погляд, у мене був просто цей дів:

<div class="fb-comments" data-href="@ViewData.Eval("currentUrl")" data-numposts="@ViewData.Eval("commentCount")" data-width="100%"></div>

0

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


0

Я вирішив цю проблему за допомогою словника.

 @Html.Partial("_Partial", new Dictionary<string, string> { { "Key1", "Val1" }, { "Key2", "Val2" }, { "Key3", "Val3" } });

-6

Щоб використовувати dynamicтип, вам потрібно посилатися на Microsoft.CSharpзбірку

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.