2016-11-30 2 views
2

Я создал вид модели под названием CompetitionRoundModel, который частично производится ниже:Проблема с Model Binding

public class CompetitionRoundModel 
{ 
    public IEnumerable<SelectListItem> CategoryValues 
    { 
     get 
     { 
      return Enumerable 
       .Range(0, Categories.Count()) 
       .Select(x => new SelectListItem 
       { 
        Value = Categories.ElementAt(x).Id.ToString(), 
        Text = Categories.ElementAt(x).Name 
       }); 
     } 
    } 

    [Display(Name = "Category")] 
    public int CategoryId { get; set; } 

    public IEnumerable<Category> Categories { get; set; } 

    // Other parameters 
} 

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

@using (Html.BeginForm()) 
{ 
    <div class="form-group"> 
     @Html.LabelFor(model => model.CategoryId, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10"> 
      @Html.DropDownListFor(model => model.CategoryId, Model.CategoryValues, new { @class = "form-control" }) 
      @Html.ValidationMessageFor(model => model.CategoryId, "", new { @class = "text-danger" }) 
     </div> 
    </div> 
    // Other code goes here 
} 

Я выбрал model.CategoryId в методе DropDownListFor(), так как я хочу, чтобы связать выбранное значение CategoryId. Мне действительно все равно CategoryValues, мне просто нужно заполнить DropDown.

Моя проблема сейчас в том, что, когда мой контроллер принимает значения для моей модели в методе действия, CategoryValues равно нулю, который приводит систему бросить ArgumentNullException (линия, которая подсвечивается является return Enumerable линия.

I даже не пробовал [Bind(Exclude="CategoryValues")], но никаких изменений вообще. Любая помощь будет очень признательна.

+0

Thanks @StephenMuecke. Ваше решение сработало. Я просто не знаю, как пометить ваш комментарий как «Ответ» здесь, чтобы вы взяли кредит. –

ответ

1

Ваш (и не должно быть) создание элементов управления формы для каждого свойства каждого Category в вашей коллекции IEnumerable<Category> так в методе POST, значение Categories является null (он никогда не инициализируется). Как только вы сделаете попытку CategoryValues, а исключение будет выбрано вашей линией кода .Range(0, Categories.Count()) в получателе.

Изменить просматривать модель, чтобы дать CategoryValues простой geter/сеттера, и удалить Categories свойство

public class CompetitionRoundModel 
{ 
    public IEnumerable<SelectListItem> CategoryValues { get; set; } 
    [Display(Name = "Category")] 
    public int CategoryId { get; set; } 
    .... // Other properties 
} 

и заполнить SelectList в методах контроллера, например

var categories db.Categories; // your database call 
CompetitionRoundModel model = new CompetitionRoundModel() 
{ 
    CategoryValues = categories.Select(x => new SelectListItem() 
    { 
     Value = x.Id.ToString(), 
     Text = x.Name 
    }, 
    .... 
}; 
return View(model); 

или альтернативно

CompetitionRoundModel model = new CompetitionRoundModel() 
{ 
    CategoryValues = new SelectList(categories, "Id", "Name"), 

Нет te также, что если вы вернете представление (потому что ModelState недействителен, вам необходимо повторно заполнить значение CategoryValues (см. The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable' для получения более подробной информации)

0

С CategoryValues просто заполняет выпадающее меню, оно никогда не будет отправлено обратно на сервер, и вам нужно будет перестроить список из базы данных до используя его в операции GET или POST. Свойством CategoryId является значение, которое будет отправлено обратно на сервер из DropDownList.