Повторное заполнение определенных значений свойств, если ModelState.IsValid имеет значение false - PullRequest
1 голос
/ 10 апреля 2011

У меня есть следующий метод действия (частичный код):

[HttpPost]
public ActionResult Create(EditGrantApplicationViewModel editGrantApplicationViewModel)
{
   if (!ModelState.IsValid)
   {
      return View("Create", editGrantApplicationViewModel);
   }

   return View("Index");
}

EditGrantApplicationViewModel выглядит следующим образом (частичный код):

public class EditGrantApplicationViewModel
{
   public IEnumerable<Title> Titles { get; set; }
   public int TitleId { get; set; }
   public IEnumerable<Bank> Banks { get; set; }
   public int BankId { get; set; }
   public IEnumerable<AccountType> AccountTypes { get; set; }
   public int AccountTypeId { get; set; }
}

Когда это Create представлениепри первом запросе я бы заполнил Titles в своем слое обслуживания и просто возвратил экземпляр EditGrantApplicationViewModel, например:

public ActionResult Create()
{
   EditGrantApplicationViewModel editGrantApplicationViewModel = grantApplicationService.CreateEditGrantApplicationViewModel();

   return View(editGrantApplicationViewModel);
}

CreateEditGrantApplicationViewModel в моем слое обслуживания:

public EditGrantApplicationViewModel CreateEditGrantApplicationViewModel()
{
   EditGrantApplicationViewModel editGrantApplicationViewModel = new EditGrantApplicationViewModel
   {
      Titles = titleRepository
         .GetAll()
         .Where(x => x.Active)
         .OrderBy(x => x.Name)
   };

   return editGrantApplicationViewModel;
}

Когда я нажимаю кнопку отправки, происходит переход к методу публикации Create.Он получает параметр editGrantApplicationViewModel типа EditGrantApplicationViewModel.Почему для свойства Titles установлено значение null?Я думал, что он сохранит значения?

Теперь допустим, что есть ошибка, ModelState.IsValid - ложь.Так что это означает, что мне придется заново заполнить свойство Titles.Учитывая значения свойств, которые были установлены в форме в editGrantApplicationViewModel, как бы я теперь заполнил свойство Titles?Я предполагаю, что мне понадобится другой метод в моих сервисных слоях, который заполняет его?Каков наилучший способ сделать это?

Любой исходный код будет оценен.

ОБНОВЛЕНИЕ 2011-04-11

На мой взгляд, яесть 3 выпадающих.Титулы, банки и типы счетов.Вот почему у меня есть 3 списка в моей модели представления.У меня есть класс обслуживания для каждого, чтобы обрабатывать вставки, обновления и получение элементов.Например, в моем классе обслуживания банка у меня были бы методы Insert, Update, GetAll, GetById и т. Д., Относящиеся к банку.У меня были бы похожие службы заголовка и типа учетной записи.

Вот как у меня это сейчас в классе контроллеров:

private IGrantApplicationService grantApplicationService;
private ITitleService titleService;
private IBankService bankService;
private IAccountTypeService accountTypeService;

public GrantApplicationController(IGrantApplicationService grantApplicationService, ITitleService titleService, IBankService bankService, IAccountTypeService accountTypeService)
{
   this.grantApplicationService = grantApplicationService;
   this.titleService = titleService;
   this.bankService = bankService;
   this.accountTypeService = accountTypeService;
}

public ActionResult Create()
{
   EditGrantApplicationViewModel editGrantApplicationViewModel = new EditGrantApplicationViewModel
   {
      // Populate the dropdown lists
      Titles = titleService
         .GetAll()
         .Where(x => x.Active)
         .OrderBy(x => x.Name),
      Banks = bankService
         .GetAll()
         .Where(x => x.Active)
         .OrderBy(x => x.Name),
      AccountTypes = accountTypeService
         .GetAll()
         .Where(x => x.Active)
         .OrderBy(x => x.Name)
   };

   return View(editGrantApplicationViewModel);
}

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

Ответы [ 2 ]

2 голосов
/ 10 апреля 2011

Сервисный слой не должен возвращать модели просмотра, он должен работать с моделями. Итак, ваш сервисный слой возвращает эти заголовки:

public IEnumerable<Title> GetTitles()
{
    return titleRepository
        .GetAll()
        .Where(x => x.Active)
        .OrderBy(x => x.Name)
    };
}

и затем передать ответственность за создание экземпляра модели представления контроллеру:

public ActionResult Create()
{
    var model = new EditGrantApplicationViewModel 
    {
        Titles = grantApplicationService.GetTitles()
    };
    return View(model);
}

[HttpPost]
public ActionResult Create(EditGrantApplicationViewModel model)
{
    if (!ModelState.IsValid)
    {
        // Reload the Titles as we are redisplaying the same view
        // and they were not part of the view model that was submitted
        model.Titles = grantApplicationService.GetTitles();
        return View("Create", model);
    }
    return View("Index");
}
0 голосов
/ 10 апреля 2011

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

Чтобы восстановить Titles, вам необходимо каким-то образом отобразить эти значения в форме, чтобы ModelBinder мог повторно обработать ваш EditGrantApplicationViewModel

Скорее всего, вам нужно будет сделать что-то вроде этого:

<% foreach(Title title in Model.Titles { %>
  <%: Html.HIddenFor(m => title) %>
<% } %>

обратите внимание, что мой синтаксис может быть немного не так, поскольку у меня нет Visual Studio на моей машине.

Также я не уверен, как ModelBinder будет обрабатывать ваш IEnumberable<T>, возможно, вам придется изменить это значение на List<T>, чтобы ModelBinder мог правильно создать тип.

Дополнительная информация о том, как привязаться к вашему списку Titles.

  1. Пост от Фила Хаака о привязке модели к списку
  2. Немного улыбнулсявопрос про mvc и IEnumerable<T>
...