MVC4 - привязка модели с частичным представлением во время отправки

У меня есть модель представления, у которой есть еще одна дочерняя модель для частичного просмотра (ниже).

public class ExamResultsFormViewModel
{
    public PreliminaryInformationViewModel PreliminaryInformation { get; set; }

    public string MemberID { get; set; }

    public string MemberName { get; set; }

    public int PatientID { get; set; }

    public string ConfirmationID { get; set; }

    public bool IsEditable { get; set; }

    #region Select Lists
    public SelectList ProviderOptions { get; set; }
    #endregion
}

public class PreliminaryInformationViewModel
{
    public string ProviderName { get; set; }

    public string ProviderID { get; set; }

    public string ServiceLocation { get; set; }
}

Эта модель представления PreliminaryInformationViewModel также используется в качестве дочерних моделей в другой модели представления, поскольку эта предварительная информация может быть обновлена ​​на разных страницах.

Итак, я создал эту предварительную информацию как отдельную часть и включил ее на другие страницы.

@{Html.RenderPartial("_PreliminaryInformation", Model.PreliminaryInformation);}

Внутри частичного

@model Web.Models.Preliminary.PreliminaryInformationViewModel
<div>
    @Html.TextBoxFor(x => x.DateOfService })
</div>

Но проблема заключается в том, что эта предварительная модель всегда равна нулю из-за того, что атрибут имени HTML всегда отображается как

но когда я передаю родительскую модель частичной, как показано ниже.

@model Web.Models.Exam.ExamResultsFormViewModel
<div>
    @Html.TextBoxFor(x => x.PreliminaryInformation.DateOfService })
</div>

Теперь элемент HTML создается как

<input type = 'text' name='PreliminaryInformation.DateOfService.DateOfService' id='PreliminaryInformation.DateOfService'>

и он правильно связывается во время отправки.

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

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

Ответ 1

Я знаю, что немного поздно, но это может кому-то помочь

Если у вас сложная модель, вы все равно можете передать ее в частичное использование:

@Html.Partial("_YourPartialName", Model.Contact, new ViewDataDictionary()
{
    TemplateInfo = new TemplateInfo()
    {
        HtmlFieldPrefix = "Contact"
    }
})

где я определил модель со свойством "Контакт". Теперь, что делает HtmlFieldPrefix, это добавляет привязку свойства для каждой модели, "чтобы связыватель модели мог найти родительскую модель"

Об этом есть сообщение в блоге: http://www.cpodesign.com/blog/bind-partial-view-model-binding-during-submit/

Привязка .NET Core 2

В .NET Core 2 и MVC ответ выше не будет работать, свойство больше не может быть установлено.

Как бы то ни было, решение очень похоже.

 @{ Html.ViewData.TemplateInfo.HtmlFieldPrefix = "Contact"; }
 @await Html.PartialAsync("_YourPartialName", Model.Contact)

после того, как вы сможете отправить свою модель, она снова свяжется.

надеюсь, это поможет

Ответ 2

Вам нужно создать шаблон редактора для PreliminaryInformationViewModel, чтобы заменить частичный вид, а затем вызвать с помощью Html.EditorFor( m => m.PreliminaryInformation ). Ссылка это решение. Создание шаблона должно быть таким же простым, как перемещение частичного представления в каталог Views/Shared/EditorTemplates. Html.EditorFor(...) будет автоматически использовать этот шаблон на основе типа, который вы передаете в качестве модели (в данном случае PreliminaryInformationViewModel)

Ответ 3

Вы можете добавить HtmlFieldPrefix в начало частичного просмотра:

@{
    ViewData.TemplateInfo.HtmlFieldPrefix = "Contact";
}

Это тот же подход, что и описанный @cpoDesign, но это означает, что вы можете сохранить префикс в частичном представлении, если вам нужно это сделать.

Ответ 4

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

@{
   Html.RenderPartial("_PreliminaryInformation", Model.PreliminaryInformation);
}

Действие, соответствующее сообщению http, искало родительскую модель. Сообщение http правильно подавало форму, но не было ссылки на ребенка, частичного родительского частичного. Представленные значения из дочернего элемента были проигнорированы, и соответствующее дочернее свойство оставалось нулевым.

Я создал интерфейс, IPreervedInfoCapable, который содержал определение для дочернего типа, например:

public interface IPreliminaryInfoCapable
{
    PreliminaryInformationViewModel PreliminaryInformation { get; set; }
}

Я сделал свою родительскую модель реализацией этого интерфейса. Затем мое частичное представление использует интерфейс вверху в качестве модели:

@model IPreliminaryInfoCapable

Наконец, мое родительское представление может использовать следующий код, чтобы передать себя дочернему частицу:

@{
    Html.RenderPartial("ChildPartial", Model);
}

Тогда дочерний частичный может использовать дочерний объект, например:

@model IPreliminaryInfoCapable
...
@Html.LabelFor(m => m.PreliminaryInformation.ProviderName)
etc.

Все это правильно заполняет родительскую модель после HTTP-сообщения соответствующим действием.

Ответ 5

Быстрый совет: при вызове метода EditorFor вы можете указать имя шаблона в качестве параметра метода Html.EditorFor. В качестве альтернативы, соглашения об именах могут быть вашим другом; просто убедитесь, что имя файла шаблона вашего редактора точно совпадает с именем типа свойства модели

то есть. тип свойства модели 'CustomerViewModel' = > 'CustomerViewModel.cshtml' шаблон редактора.

Ответ 6

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

//Parent Page
@{Html.RenderPartial("_PreliminaryInformation", Model.PreliminaryInformation);}

//Partial Page
@model Web.Models.Preliminary.PreliminaryInformationViewModel
@using (Html.BeginCollectionItem("PreliminaryInformation", item.RowId, true))
    {
<div>
@Html.TextBoxFor(x => x.DateOfService })
</div>

}

Ответ 7

Для .net core 2 и mvc используйте do как ниже:

@{
 Html.ViewData.TemplateInfo.HtmlFieldPrefix = "Contact"; 
}
 @await Html.PartialAsync("_YourPartialViewName", Model.Contact)