ASP.NET MVC: использование одного и того же ViewModel для рендеринга страницы и получения результатов - PullRequest
2 голосов
/ 13 ноября 2009

Вот простая модель вида, которую я использую:

public class ViewModel
{
  public Order Order { get; set; }
  // returned from page - also can be pre-selected
  public string[] SelectedProducts { get; set; }
  // data for page to render available products to select from
  public IList<ProductViewModel> AvailableProducts { get; set; }
}

public ActionResult Edit(Order order)
{
   return View(new ViewModel { Order = order, SelectedProducts = new string[0], AvailableProducts = repository.GetAvailable() });
}

(обратите внимание, что Order автоматически связывается с пользовательским связывателем модели в POST)

Теперь я возвращаю View (новый ViewModel (...)), и он работает. Страница GET / Edit отображает доступные продукты, пользователь выбирает их, а затем отправляет выбранные POST / Edit действия, выбранные из SelectedProducts.

Проблема в том, что пользовательский ввод недопустим - мне нужно повторно отобразить страницу, не касаясь введенных пользовательских данных, но при этом предоставить доступный продукт. Просто return View (data) не будет работать, потому что AvailableProducts не является частью предоставленных данных и имеет значение null.

Вопрос: как мне решить проблему? Я могу сделать

public ActionResult(ViewModel data)
{
   if (!ModelState.IsValid)
   {
      data.AvailableProducts = repository.GetAvailable();
      return View(data);
   }
}

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

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

Ответы [ 2 ]

3 голосов
/ 13 ноября 2009

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

private ViewModel PopulateModelForView( Order order, string[] products )
{
     return new ViewModel
            {
                Order = order,
                SelectedProducts = products ?? new string[],
                AvailableProducts = repository.GetAvailable()
            };
}

public ActionResult Edit(Order order)
{
   return View( PopulateModelForView( order, null) );
}

public ActionResult Update(ViewModel data)
{
   if (!ModelState.IsValid)
   {
      return View( PopulateModelForView( data.Order, data.SelectedProducts ) );
   }
}
0 голосов
/ 13 ноября 2009

Что я делаю, это просто создаю новое представление с моим входным вводом в качестве аргументов. Так что это:

public ActionResult Create([Bind(Exclude = "Id")]Profiles profileToAdd)
{
        try{
            your shiny code here
        }
        catch{
            return View(new ProfileFormViewModel(profileToAdd));
        }
}

, и это оставляет место, которое не заполнено правильно красным цветом, и остальные параметры, которые вы уже правильно установили. Я не знаю, если это то, что вы ищете?

В вашем случае вы можете либо позволить списку войти в метод в качестве ввода, либо сгенерировать его снова. Что угодно. Затем отправьте его через вашу модель просмотра (отредактировано):

public ActionResult Create(Order order, IList<ProductViewModel> AvailableProducts)
{
        try{
            UpdateModel(order);
            SaveChanges();
        }
        catch{
            return View(new ViewModel(order, AvailableProducts));
        }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...