редактирование модели в нескольких представлениях

#c# #ajax #asp.net-mvc

#c# #ajax #asp.net-mvc

Вопрос:

Моя цель — изменить модель в более чем одном представлении. Поскольку иногда мои модели имеют много свойств, я хочу изменить их в нескольких представлениях. Что-то вроде:

первая страница редактирует 2 свойства, вторая страница редактирует 3 других свойства,…

модель выглядит следующим образом:

 public class LoadViewModel
{
    public int CurrentPage { get; set; } = -1;
    public PageViewModel PageViewModel { get; set; }
}

public class PageViewModel
{
    public string Param1 { get; set; }
    public string Param2 { get; set; }
    public int Param3 { get; set; }
}
  

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

 @model LoadViewModel
@using(Ajax.BeginForm("Load", "Home", new AjaxOptions {UpdateTargetId = "page"}, new {lvm = Model}))
{
    <div id="page"></div>
    <input type="submit"/>
}
  

и это мое действие:

 public ActionResult Load(LoadViewModel lvm = null)
{
    if (lvm == null) lvm = new LoadViewModel();
    lvm.CurrentPage  = 1;
    TempData["CurrentPage"] = TempData["CurrentPage"] == null ? 0 : (int)TempData["CurrentPage"]   1;
    if (!partialViewDict.ContainsKey((int) TempData["CurrentPage"]))
        TempData["CurrentPage"] = 0;
    return PartialView(partialViewDict[(int)TempData["CurrentPage"]], lvm);
}
  

страницы — это просто отображаемые части:

 private Dictionary<int, string> partialViewDict = new Dictionary<int, string>
{
    {0, "Pages/_Page1"},
    {1, "Pages/_Page2"},
    {2, "Pages/_Page3"},
};
  

и спроектирован так:

 @using WebApplication1.Controllers
@model LoadViewModel
@{
    TempData["CurrentPage"] = 0;
}

@Html.DisplayNameFor(m => m.PageViewModel.Param1)
@Html.EditorFor(m => m.PageViewModel.Param1)
  

это работает. При переключении на страницу 2 модель задана правильно, но при нажатии submit значение Param1 (которое я установил на странице 1) сбрасывается null , и только значения, которые я установил в текущей части, являются правильными.

Это страница 2:

 @using WebApplication1.Controllers
@model LoadViewModel
@{
    TempData["CurrentPage"] = 1;
}
@Html.DisplayNameFor(m => m.PageViewModel.Param2)
@Html.EditorFor(m => m.PageViewModel.Param2)
  

Когда я добавляю a @Html.HiddenFor(m => m.PageViewModel.Param1) в частичное, значение по-прежнему устанавливается. Но я не хочу, чтобы значения были сброшены. Я не хочу добавлять @Html.HiddenFor для всех свойств набор в предыдущем представлении. Как я могу предотвратить сброс значений при нажатии submit без добавления @Html.HiddenFor для всех не перечисленных атрибутов? Или есть какая-либо другая возможность поймать мою цель?

Ответ №1:

В этом есть две части. Во-первых, сам post и получение его для проверки. Для этого каждый шаг должен иметь свою собственную модель представления, содержащую только те свойства, которые он должен изменять. Это позволяет вам добавлять все необходимые проверки, не вызывая сбоев в других шагах. В конце вы объедините данные из всех этих объектов в свой класс сущностей или что-то еще.

Что подводит нас ко второй части. Вам нужен какой-то способ сохранения данных с каждого шага. Единственные данные, которые будут существовать после публикации, — это данные, которые были опубликованы, и все, что было в сеансе (который включает TempData в себя ). Вы всегда можете создать кучу скрытых полей для хранения данных из предыдущих шагов, но это может быть немного сложно. Скорее всего, вы просто захотите использовать сеанс.

TempData по сути, это специализированный экземпляр Session , поэтому то, что вы используете, на самом деле не имеет значения. С TempData помощью call вам нужно будет запоминать call TempData.Keep() для каждого из ключей, которые вы установили для каждого шага, иначе вы потеряете предыдущие шаги при следующем запросе. Session сохранит их в течение всего сеанса, но вы должны помнить, чтобы удалить ключи в конце с Session.Remove() помощью .

Комментарии:

1. хм .. так что, может быть, создать viewmodel для каждого шага, а затем позже сопоставить их с одним, если будет отправлен последний шаг? (Я могу сохранить их в базе данных только в том случае, если был отправлен последний шаг) — Если этим занимаются 2 человека, они не будут переопределять TempData-объект от другого пользователя?

2. Совсем нет. Session / TempData зависит от клиента. На клиенте устанавливается файл cookie, который однозначно идентифицирует данные сеанса.

3. хорошо, и у вас есть идея, может ли это быть проблемой с производительностью для хранения большой viewmodel в таких временных данных? (возможно, 50 свойств с большими строками). Таким образом, я мог бы при отправке сопоставить viewmodel страницы с большой viewmodel (например, AutoMapper), которая может быть сохранена в базе данных, когда пользователь все закончил. Будет ли это хорошей процедурой?

4. Производительность не должна быть проблемой. Однако, в зависимости от вашего хранилища сеансов, могут быть вещи, которые следует учитывать. В proc используется память, поэтому очевидно, что чем больше вы это делаете, тем больше оперативной памяти потребуется вашему серверу. Это не значит, что вам нужно полностью использовать оперативную память. Это просто то, что вам нужно отслеживать. Если вы используете SQL Server или SessionState Server, вам нужно убедиться, что все, что вы туда вводите, имеет примитивный тип или может быть сериализовано в строку XML / JSON.

5. Хорошо. 🙂 Спасибо, что поделились своими знаниями 🙂

Ответ №2:

Используете ли вы @using (Html.BeginForm()) в вашем .cshtml?

К сожалению, это MVC. MVC не имеет состояния, что означает, что если вы не отобразите его, вы потеряете его: (

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

Комментарии:

1. но должно быть какое-либо решение для изменения модели в более чем одном представлении !? в противном случае, это кажется действительно статичным .. моя цель — создать поток установки, в котором пользователь может инициализировать и настраивать приложение (как Windows после установки ОС) — и ему не придется прокручивать ironman (226 км). Нет, я уже использую Ajax.BeginForm() . с Html.BeginForm() этим невозможно

2. Незначительная придирка, но просто хочу уточнить: HTTP не имеет состояния. На самом деле MVC таковым не является, поскольку он поддерживает концепцию сеансов, которые добавляют состояние. Однако, если предположить, что сеансы не используются, запросы будут «без состояния».