Создание формы MVC с использованием частичных представлений, каждое из которых содержит сложные модели, не привязанные к основной модели.

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

Я попытался изменить Html.RenderPartial на Html.EditorFor, и хотя это устранило мою проблему с привязкой модели, оно удалило все мое форматирование html из частичного представления.

Есть ли способ привязать элементы частичного представления к основной модели формы или сохранить структуру html моего частичного представления с помощью EditorFor?

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

Это моя модель:

public class ShipJobs
{
    public String Job { get; set; }
    public String Quote { get; set; }
    public String PartName { get; set; }
    public String Rev { get; set; }
    public String Customer { get; set; }
    public String CustomerName { get; set; }
    public String TrackingNumber { get; set; }
    public Int32 ShippedQuantity { get; set; }
    public Boolean Certs { get; set; }
    public Double ShippingCharges { get; set; }
    public DateTime ShipDate { get; set; }
    public String SelectedFreightTerms { get; set; }
    public IEnumerable<SelectListItem> FreightTerms { get; set; }
    public String SelectedContact { get; set; }
    public IEnumerable<SelectListItem> Contacts { get; set; }
    public String SelectedShipVia { get; set; }
    public IEnumerable<SelectListItem> ShipVia { get; set; }
    public Models.GreenFolders.Address Address { get; set; }
}

public class Address
{
    public AddressType Type { get; set; }
    public String ShipToId { get; set; }
    public String ContactName { get; set; }
    public String AddressName { get; set; }
    public String Line1 { get; set; }
    public String Line2 { get; set; }
    public String City { get; set; }
    public String State { get; set; }
    public String Zip { get; set; }

    public String Phone { get; set; }
    public SelectList ShipToAttnDropDown { get; set; }
    public IEnumerable<SelectListItem> ShipToDropDown { get; set; }
}

Контроллер:

public ActionResult ShipJobs(String Job, Models.Shipping.ShippingModel.ShipJobs Packlist, Models.GreenFolders.Address ShipAddress, String Submit = "")
{
    var Model = new Models.Shipping.ShippingModel.ShipJobs();

    if (Submit == "loadjob")
    {
        var shippingHelper = new BLL.Shipping.ShippingMethods(_company);
        Model = shippingHelper.GetShipJobModel(Job);
        Model.Address = shippingHelper.GetShipAddress(Job);
    }
    else if (Submit == "createpacklist")
    {

    }

    ViewBag.Company = _company.ToString();
    return View(Model);
}

Основной вид:

@model Models.Shipping.ShippingModel.ShipJobs

@{
    ViewBag.Title = "ShipJobs";
    String Company = ViewBag.Company.ToString();
}

@using (Html.BeginForm("ShipJobs", "Shipping", FormMethod.Post, new { Class = "form-horizontal" }))
{
<div class="row">
    <div class="col-md-6">

        <!-- Basic Form Elements Block -->
        <div class="block">
            <!-- Basic Form Elements Title -->
            <div class="block-title">
                <h2>Load <strong>Job</strong></h2>
            </div>
            <!-- END Form Elements Title -->
            <!-- Basic Form Elements Content -->
            @using (Html.BeginForm("ShipJobs", "Shipping", FormMethod.Post, new { Class = "form-horizontal form-bordered" }))
            {
                <div class="form-group">
                    <label class="col-md-3 control-label" for="example-text-input">Job Number</label>
                    <div class="col-md-9">
                        @Html.TextBoxFor(model => model.Job, new { id = "example-text-input", Name = "Job", Class = "form-control" })
                    </div>
                </div>
                <div class="form-group form-actions">
                    <div class="col-md-9 col-md-offset-3">
                        <button type="submit" class="btn btn-sm btn-primary" name="submit" value="loadjob"><i class="fa fa-angle-right"></i> Load Job Info</button>
                        <button type="reset" class="btn btn-sm btn-warning"><i class="fa fa-repeat"></i> Reset</button>
                    </div>
                </div>
            }
        </div>


    </div>
    <div class="col-md-6">
        @if (Model.Address != null && Model.Address != null)
        {
            @Html.EditorFor(model => model.Address)
            //Html.RenderPartial("../Shared/_Address", Model.ShipInfo);
        }


    </div>
    @Html.HiddenFor(model => model.Quote)
    @Html.HiddenFor(model => Company)
</div>
}

Частичный вид:

@model Models.GreenFolders.Address

<!-- Block -->
<div class="block">
    <div class="block-title">
        @if(Model.Type == Models.GreenFolders.AddressType.Shipping)
        {
            <h2 style="float: right; margin-top: -9px; margin-right: -10px;">
                <div class="dropdown shiptoddl">
                    <button class="btn btn-default dropdown-toggle" type="button" id="shiptoddl" data-toggle="dropdown" aria-expanded="true">
                        @Model.ShipToDropDown.Where(x => x.Selected).FirstOrDefault().Text
                        <span class="caret"></span>
                    </button>
                    <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
                        @foreach (SelectListItem selectlistitem in Model.ShipToDropDown)
                        {
                            <li role="presentation"><a role="menuitem" tabindex="-1" href="#" data-value="@selectlistitem.Value" data-selected="@selectlistitem.Selected">@selectlistitem.Text</a></li>
                        }
                    </ul>
                </div>
                @*@Html.DropDownList("shiptoddl", (SelectList)Model.ShipToDropDown, new { @class = "shiptoddl", id = "shiptoddl" })*@
            </h2>
        }
        <h4><strong>@Model.Type.ToString()</strong> Address</h4>
    </div>
    @{ Html.RenderPartial("../Shared/_AddressDetails", Model); }
</div>
<!-- END Block -->

person someguy0005    schedule 28.01.2015    source источник
comment
У вас не может быть вложенных форм (это недопустимый html и не поддерживается!). Частичное не будет работать, если вы не передадите префикс (см. >этот ответ), но лучшим решением является EditorFor(), но вам нужно создать собственный EditorTemplate для Address, который содержит элементы управления и форматирование, которое вы хотите   -  person    schedule 28.01.2015
comment
Спасибо, Стивен, я не беспокоюсь о вложенных формах, мои действия отлично с этим справляются. Есть ли у вас примеры того, как превратить отформатированное частичное представление в EditorTemplate? Я не мог найти ничего подобного в своем исследовании до того, как задать вопрос. В качестве резервной копии прекрасно подойдет решение с префиксом, но я предпочитаю научиться правильно использовать EditorTemplate. Спасибо!   -  person someguy0005    schedule 28.01.2015
comment
Вы должны беспокоиться, что он недействителен и не поддерживается одинаково в разных браузерах, и даже если он работает для вас сейчас в одном браузере, он может сломаться для более новой версии (есть много вопросов/ответов на SO по этому поводу - НЕ ДЕЛАЙТЕ ЭТО). Что касается шаблона, добавьте в /Views/Shared/EditorTemplates представление с именем Address.cshtml и скопируйте в него свое частичное представление.   -  person    schedule 28.01.2015
comment
Почти готово... Я использую переопределение, указывающее имя моего шаблона редактора (поскольку оно не соответствует имени свойства моей модели). Это устранило проблемы с форматированием, но не отправляет значения шаблона редактора обратно в форму отправки. Я также удалил внутреннюю форму, так как вы были правы (она мне вообще не нужна, моя внешняя форма уже справилась с этим - спасибо за подсказку). Вам нужен обновленный код?   -  person someguy0005    schedule 28.01.2015
comment
Вы не можете использовать перегрузку, которая указывает имя редактора (который не будет правильно добавлять префикс, поэтому вы все равно получите name="City" вместо name="Address.City", который вам нужен для привязки к вашей модели ShipJobs. Имя шаблона должно соответствовать имени class (имя свойства не имеет значения), поэтому, если у вас есть typeof Address, шаблон должен быть Address.cshtml   -  person    schedule 28.01.2015
comment
Понял, большое спасибо, Стивен! Проблема, с которой я столкнулся, когда моя модель неправильно привязывалась, заключалась в том, что в моем частичном представлении отображалось содержимое модели без использования DisplayFor или TextBoxFor или любых других средств сохранения привязки неповрежденной. Вот почему, когда у меня был шаблон редактора по умолчанию для моей модели, он работал отлично. Просто оставлю этот след на случай, если у кого-то еще будет такая же проблема, как у меня.   -  person someguy0005    schedule 28.01.2015
comment
И еще несколько комментариев: это new { @class = "form-control" } и не используйте new { Name = ".." } (никогда не пытайтесь переопределить атрибут name, если вы не хотите, чтобы привязка завершилась ошибкой)   -  person    schedule 28.01.2015