Неверное значение свойства модели отображается в частичном представлении

У меня есть строго типизированное частичное представление, модель которого содержит свойство с тем же именем, что и модель представления родительской страницы. По какой-то причине механизм рендеринга отображает значение модели родительского представления, а не ожидаемое значение (ну, по крайней мере, значение, которое я ожидаю!)

Извлечение модели представления родительской страницы:

public class ParentPageViewModel
{
    public int Id { get; set; } // problem property
    ...
    public IEnumerable<ChildViewModel> Children { get; set; }
}

Извлечение модели просмотра дочерней страницы:

public class ChildViewModel
{
    public int Id { get; set; } // problem property
    ...
}

Извлечение родительской страницы (Razor):

@model ParentPageViewModel
...
@foreach (var item in Model.Children)
{
    @Html.Partial("MyPartialView", item)
}
...

Извлечение частичного представления:

@model ChildViewModel
...
<form ...>
    @Html.HiddenFor(m => m.Id) // problem here - get ParentPageViewModel.ID not ChildViewModel.Id
</form>
...

Таким образом, в основном в моем отображаемом выводе мое скрытое поле имеет значение элемента модели родительского представления, а НЕ значение, переданное частичному представлению. Это определенно вызвано именем, поскольку изменение имени @ChildViewModel.Id@ на что-то вроде @ChildViewModel.ChildId@ заставляет его работать должным образом. Интересно, что при проверке значений модели представления в отладчике я вижу правильные значения; это только визуализированный вывод, который неверен.

Есть ли способ обойти это или «правильный» способ сделать то, что я пытаюсь сделать (я отображаю мини-формы в таблице для проверки/публикации обновлений строк таблицы ajax)

Спасибо,

Тим


person Tim Croydon    schedule 07.08.2012    source источник
comment
HtmlHelpers сначала возьмет значения из словаря ModelState (даже по сравнению со значением в модели) - похоже, это причина такого поведения.   -  person Simon    schedule 07.08.2012


Ответы (4)


Я думаю, что изменение вашего вызова на это решит проблему:

@Html.Partial("MyPartialView", item, new ViewDataDictionary())

Дочернее представление берет значение из словаря ViewData, поэтому оно передается в новом словаре дочернему представлению (hattip danludwig).

person Simon    schedule 07.08.2012
comment
+1 Я тоже собирался добавить это в свой ответ, но мне пришлось уйти, прежде чем я смог закончить. Вы правы, дочерняя модель получает идентификатор из родительского словаря данных представления. - person danludwig; 07.08.2012
comment
Да, это работает, хотя на самом деле я использовал свой собственный ответ (созданный вручную тег ‹input›), поскольку мое частичное представление используется повсюду, поэтому я хотел избежать риска забыть часть «new ViewDataDictionary()». Спасибо. - person Tim Croydon; 22.08.2012
comment
@TimCroydon, чтобы предотвратить этот риск, вы можете создать метод расширения HtmlHelper, который делает это, а также означает, что вы также можете жестко закодировать имя «MyPartialView» в одном месте. - person Simon; 22.08.2012

Нашел решение, просто вручную создав скрытое поле, например:

<input type="hidden" name="Id" value="@Model.Id" />

вместо использования Html.HiddenFor.

(Я не буду отмечать это как ответ на какое-то время, если есть какие-либо другие решения или кто-нибудь может объяснить проблему)

person Tim Croydon    schedule 07.08.2012

Я знаю это старый пост. Но я подумал, что, поскольку я приземлился здесь, когда столкнулся с той же проблемой, я мог бы внести свой вклад. Моя проблема была немного другой. В моем случае идентификатор основного представления был неправильным после запуска действия частичного просмотра, которое требовало обновления всей страницы/представления. Я решил проблему с ModelState.Clear

ModelState.Clear();
return View("Maintenance", model);  //call main view from partial view action
person Ntho    schedule 26.06.2016

Создайте файл с именем ChildViewModel.cshtml в Views/Shared/EditorTemplates. Поместите свое частичное представление в этот файл:

в ~/Views/Shared/EditorTemplates/ChildViewModel.cshtml

@model ChildViewModel
...
<form ...>
    @Html.HiddenFor(m => m.Id)
</form>
...

Затем визуализируйте это так:

@model ParentPageViewModel
...
@foreach (var item in Model.Children)
{
    @Html.EditorFor(m => item)
}
...

Или, если вы предпочитаете сохранить представление как частичное, а не как шаблон редактора, используйте ответ Саймона.

person danludwig    schedule 07.08.2012