2015-06-19 3 views
-1

При обработке сообщений о формах в MVC я нахожу, что я пишу несколько, несколько утомительный код, чтобы убедиться, что опубликованные выпадающие списки выбраны для действительных элементов в список. Идея заключается в том, что нет ничего, что помешает сообщению, содержащему выбранный идентификатор, который не был первоначально представлен в раскрывающемся списке. Пользователь может вставить свой собственный элемент в раскрывающийся список (или иначе отправить все, что захочет), или, может быть, форма сидела в окне так долго, что элементы, которые теперь доступны, изменились. Независимо от того, почему это может произойти, факт заключается в том, что вы не можете контролировать отправленные данные. Вот пример кода, как я справляюсь с:ASP.NET MVC для проверки выбора выбранного (выпадающего) списка выбранных элементов

VM:

public class MyViewModel 
{ 
    public string SelectedItemID {get; set;} 

    public List<Items> AvailableItems {get; set;} 
} 

Вид:

@using (Html.BeginForm()) 
{ 
    @Html.DropDownListFor(m => m.SelectedItemID, 
           Model.AvailableItems.Select(i => new SelectListItem() 
           { 
            Value = i.ID.ToString(), 
            Text = i.Name, 
            Selected = (Model.SelectedItemID == i.ID) 
           }), "Select One") 
} 

Контроллер:

[HttpPost] 
public ActionResult Index(MyViewModel myVM) 
{ 
    bool isValid = true; 

    try 
    { 
     //Reload the available items 
     myVM.AvailableItems = Repository.GetAvailableItems(); 

     if(!ModelState.IsValid) 
     { 
      isValid = false; 
     } 
     else 
     { 
      //Make sure the SelectedItemID is a real item 
      if(!myVM.AvailableItems.Any(i => i.ID == myVM.SelectedItemID)) 
      { 
       isValid = false; 
       myVM.SelectedItemID = null; 
       ModelState.AddModelError("SelectedItemID", "Required"); //This gets interesting when the selected ID belongs to a nested VM in a collection. 
      } 
     } 

     if(isValid) 
     { 
      //Finally I can process the form 
     } 
    } 
    catch(Exception) 
    { 
     ModelState.AddModelError("", "Unable to process your submission. Please try again."); 
    } 

    //return an ActionResult 
} 

Установка ошибки в ModelState получает особенно некрасиво, если SelectedItemID принадлежит к вложенной модели представления, находящейся внутри коллекции. Кажется, что это должен быть стандартный тип проверки, но, относительно простоты выполнения другой проверки в asp.net MVC, это довольно уродливо и утомительно. Есть ли более простой способ позаботиться об этом?

+0

Примечание: вы можете удалить 'Selected = (Model.SelectedItemID == i.ID)'. Ваша привязка к свойству, поэтому установка свойства 'Selected'' SelectListItem' игнорируется - это просто лишние дополнительные накладные расходы. –

+0

@ StephenMuecke Я нашел, что это не так. Без настройки «Выбранный» раскрывающийся список выглядит пустым, если для параметра Model.SelectedItemID установлено значение, существующее в списке. – xr280xr

+0

Тогда вы не понимаете, что делает этот метод. Вы можете установить свойство 'Selected' на то, что вам нужно, и оно будет проигнорировано. Внутренний метод 'DropDownListFor()' создает собственный новый 'IEnumerable 'и устанавливает свойство« Выбранное »на основе значения свойства, к которому вы привязываетесь. –

ответ

0

Я думаю, вы должны смотреть на ответ Тима Кокера здесь:

Is it possible to update ModelState.IsValid manually?

В принципе, вы хотите, чтобы ваш ViewModel класс наследует от IValidatableObject, а затем поставить некоторые VALIDATE логику в нее. Последующие проверки не должны выполняться, если ваши критерии не выполняются (т.е. SelectedItemId не в новом запросе db)

+0

Спасибо за идею. Это поможет упростить добавление ошибки в ModelState.Однако в примерах реального мира ViewModel, содержащий свойство выбранного идентификатора, может не содержать коллекцию и/или может не иметь контекстуальных данных, необходимых для ее получения. – xr280xr

Смежные вопросы