Потеря данных в моделях и коллекциях внутри ViewModel при обратной передаче - PullRequest
1 голос
/ 05 января 2012

Я использую модель представления, которая содержит несколько других моделей (сущностей) для каждого частичного представления. Я отрисовываю частичное представление, передавая объект, который находится внутри ViewModel. Мой частичный вид имеет несколько полей и несколько кнопок. При нажатии кнопки (которая находится внутри моего частичного представления) форма отправляется обратно с данными в подчиненном объекте, в то время как моя модель представления всегда отправляется обратно как нулевая ... Мне нужно, чтобы данные присутствовали в моей модели представления на обратной странице.

Все виды строго набраны:

Код:

public class OrdersVM
{
    public FiltersVM filterCriteria { get; set; }
    public IEnumerable<MeterInventory> meters { get; set; }
    public string assignTo { get; set; }
    public IEnumerable<SelectListItem> AssigneeOptions { get; set; }
}

public partial class Meters
{
    public int MTRNO { get; set; }
    public string LOCName { get; set; }
}

public class FiltersVM
{
    public string Center { get; set; }
    public DateTime? DueDate { get; set; }
}

Посмотреть код

@model OrdersVM
@{
    ViewBag.Title = "Orders";
}
@using (Html.BeginForm())
{   
    <div>
        @Html.Partial("~/Views/Base/Filters.cshtml", Model.filterCriteria)
    </div>
    @foreach (var item in Model.meters)
    {  
    <table>
        <tr>
            <td>
                @Html.Encode(item.LOCNAME)
            </td>
        </tr>
    </table>
    }
}

Код контроллера

[HttpPost]
public ActionResult Index(OrdersVM orders, FiltersVM filters)
{
    //orders is null
    //filters has values
}

Спасибо, Оливхур. Я использую частичное представление "Filters.cshtml". и я делаю то же самое.

Ниже приведен код для частичного просмотра:

@model ViewModels.FiltersVM  <fieldset>
    <legend>Order Assignment</legend>
    <table id="tbl1" class="tableforcontrols">
        <tr>
            <td>
                <div class="editor-label">
                    @Html.LabelFor(model => model.LDC)
                </div>
            </td>
            <td>
                <div class="editor-field">
                    <input type="submit" value="Search" id="btnSearch" name="button" />
                </div>
            </td>
            <td>
                <div class="editor-field">
                    <input type="submit" class="cancel" value="Reset" id="btnReset" name="button" />
                </div>
            </td>
        </tr>
    </table>    </fieldset>     

Я попытался с одним аргументом "OrdersVM" (модель родительского представления), но безуспешно.

[HttpPost]
public ActionResult Index(OrdersVM orders)

но если я передам родительскую модель представления частичному представлению, оно будет содержать данные в OrdersVM.filterCriteria, но не для свойств (IEnumerable метров, string assignTo и Enumerable AssigneeOptions)

@Html.Partial("~/Views/Base/Filters.cshtml", Model)

Я новичок в MVC. Пожалуйста, дайте мне знать, если кто-нибудь найдет решение.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 29 марта 2015

Звучит так, как будто вы пришли с веб-форм.Для перехода на MVC нужно удалить мысль о PostBack.Это концепция, которой на самом деле не существует в Интернете, но Webforms подделали ее для нас.

В MVC вы обычно начинаете с запроса GET, например / edit / {someId}.Отсюда вы загружаете данные для модели представления из базы данных и визуализируете представление.Теперь предположим, что все данные в модели представления доступны для редактирования, поэтому каждое свойство имеет свое собственное поле ввода.Пользователь редактирует некоторые данные и сохраняет форму.Это выдает POST на сервер.

Предположим, у нас есть этот метод POST

[HttpPost]
public ActionResult Edit(MyViewModel model)

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

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

[HttpPost]
public ActionResult Edit(MyViewModel model){
   return View(model);
}

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

public int CarId { get; set; }
public IEnumerable<SelectListItem> CarOptions {get; set; }

Когда вы публикуете форму на этот раз, CarId будет заполняться в ViewModel, но не CarOptions, потому что они не являются частью данных формы.Если вы захотите вернуть тот же самый вид снова, вам нужно перезагрузить недостающие части.

[HttpPost]
public ActionResult Edit(MyViewModel model){
   model.CarOptions = LoadCarOptions();
   return View(model);
}

Конечно, можно связать это и с моделью, если поместить его в скрытое поле.Но проще и, вероятно, более эффективно снова загрузить его с сервера / базы данных.Это нормальный подход при работе с MVC.

0 голосов
/ 05 января 2012

Похоже, у вас здесь есть пара проблем. Одна из вероятных причин, по которой arg-ордера в вашем методе действия равна нулю, заключается в том, что не похоже, что вы визуализируете какие-либо элементы ввода. У вас просто есть @Html.Encode(item.LOCNAME).

Чтобы связыватель модели по умолчанию создал экземпляр OrdersVM и передал его методу действия, он должен иметь входные данные из HTTP POST. Вам нужно что-то более похожее на @Html.TextBoxFor(m => item.LOCNAME).

Вторая проблема, я думаю, состоит в том, что у вас есть 2 аргумента в методе действия. Поскольку OrdersVM уже имеет свойство FiltersVM, у вас должна быть возможность иметь единственный аргумент OrdersVM для метода действия. Во время HTTP POST вы можете просто получить доступ к FiltersVM свойствам из OrdersVM.filterCriteria. Однако это приведет к вашей третьей задаче, поскольку свойство meters в OrdersVM является коллекцией IEnumerable.

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

Если вам не нравится использовать целые числа для индексации полей коллекции, есть помощник HTML , написанный Стивом Сандерсоном , который позволяет индексировать входные данные коллекции с использованием идентификаторов GUID. Мы используем это все время, но это может быть сложно - в основном, вы должны всегда помещать элемент коллекции в частичное представление. На данный момент вам может быть лучше использовать целочисленную индексацию, как описано в статье Haacked.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...