2015-09-15 2 views
1

У меня проблема с моей обратной записью из DropDownList. Я пытаюсь создать страницу, которая позволит пользователям создавать новый набор навыков, но набор навыков связан с категориями навыков, поэтому я использую DropDownList, чтобы пользователь мог выбрать категорию, к которой относится набор навыков, но я получаю это исключение :Значение ASP.NET MVC не может быть нулевым. on DropDownList

исключение типа «System.ArgumentNullException» произошло в System.Web.Mvc.dll, но не был обработан в пользовательском коде

Дополнительная информация: Значение не может быть пустым.

Это мои контроллеры для создания:

// GET: SkillSets/Create 
public ActionResult Create() 
{ 
    var categoryIDs = db.Categories.Where(c => c.Active == 1).Select(x => x.IDCategory).Distinct(); 
    List<SelectListItem> items = new List<SelectListItem>(); 
    foreach (var t in categoryIDs) 
    { 
     SelectListItem s = new SelectListItem(); 
     s.Text = t.ToString();//db.Categories.Where(c => c.IDCategory == t & c.Active == 1).Select(x => x.Category + ": " + x.C_Role).Single(); 
     s.Value = t.ToString(); 
     items.Add(s); 
    } 
    ViewBag.Campaign = items; 
    return View(); 
} 

// POST: SkillSets/Create 
[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Create([Bind(Include = "IDSkillset,IDCategory,Product,P_Version,Notes")] Models.SkillSetsModel ss) 
{ 
    try 
    { 
     if (ModelState.IsValid) 
     { 
      db.SkillSets.Add(ss); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
     return RedirectToAction("Index"); 
    } 
    catch 
    { 
     return View(); 
    } 
} 

И это DropDownList:

<div class="form-group"> 
    @Html.LabelFor(model => model.IDCategory, htmlAttributes: new { @class = "control-label col-md-2" }) 
    <div class="col-md-10"> 
     @Html.DropDownList("Campaign", new SelectList(ViewBag.Campaign, "Value", "Text"), new { htmlAttributes = new { @class = "form-control" } }) 
     @Html.ValidationMessageFor(model => model.IDCategory, "", new { @class = "text-danger" }) 
    </div> 
</div> 

Вот модель:

namespace ITSSkillsDatabase.Models 
{ 
    [Table("SkillSets")] 
    public class SkillSetsModel 
    { 
     [Key] 
     public int IDSkillset { get; set; } 

     public int IDCategory { get; set; } 

     public string Product { get; set; } 

     [Display(Name = "Product Version")] 
     public string P_Version { get; set; } 

     public string Notes { get; set; } 

     public virtual ICollection<PersonSkillsModel> PersonSkills { get; set; } 
    } 
} 

DropDownList работает для Получите часть метода create, там, похоже, есть проблемы w либо с представлением, либо с методом Post, поскольку заполняется DropDownList. enter image description here

+0

Где вы получаете эту ошибку? это в сообщении или получении страницы? – Canvas

+0

Что ты Модель? Почему у вас есть привязка dropdownlist к свойству «Кампания», которое даже не существует (и все равно исключается вашим атрибутом '[Bind"]. Почему вы создаете 'SelectList' в контроллере, а затем создаете другой 'SelectList' из него в представлении? –

+0

@Canvas Сообщение, поскольку ошибка возникает только при попытке создать набор навыков, DropDownList также полностью заполнен – TheHornyDonut

ответ

0

Изменение:

@Html.DropDownList("Campaign", new SelectList(ViewBag.Campaign, "Value", "Text"), new { htmlAttributes = new { @class = "form-control" } }) 

в

@Html.DropDownListFor(m => m.IDCategory, (IEnumerable<SelectListItem>)ViewBag.Campaign) 

исправили проблему, спасибо @StephenMuecke!

+0

Кстати, это сработало бы как '@ Html.DropDownList (« IDCategory », новый SelectList (ViewBag.Campaign,« Значение »,« Текст »), новый {htmlAttributes = new {@class =" form-control "}}) '. Когда вы привязываетесь к модели на столбе, ваши поля должны соответствовать именам свойств – Eonasdan

1

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

@Html.DropDownListFor(m => m.IDCategory, (IEnumerable<SelectListItem>)ViewBag.Campaign) 

Обратите внимание, что ViewBag свойство уже IEnumerable<SelectListItem> поэтому использование new SelectList(ViewBag.Campaign, "Value", "Text") просто бессмысленно дополнительные накладные расходы (вы строите новый IEnumerable<SelectListItem> из выходящего)

Однако ваш код имеет множество других ошибок.

В методе GET вы выбираете только свойство ID Category, а затем используете .Distinct(). Если ваши свойства идентификатора еще не уникальны, это говорит о проблеме с вашей структурой базы данных. Вы также показываете только идентификационное значение в представлении, которое вряд ли имеет смысл для пользователя. Предполагая, что Category имеет свойство (скажем) string Name для описания категории, вы можете упростить ваш код

public ActionResult Create() 
{ 
    ViewBag.Campaign = db.Categories.Where(c => c.Active == 1).Select(c => new SelectListItem 
    { 
    Value = c.IDCategory.ToString(), 
    Text = c.Name 
    }); 
    return View(new SkillSetsModel()); // always return a model 
} 

Обратите внимание на то, что IsActive свойство является int, а не bool также предлагает проблемы с базой данных/дизайн модели ,

В методе POST вы в настоящее время перенаправляетесь на другой вид, если ModelState недействителен, то есть пользователь не знает, что данные, которые они только что заполнили, не были сохранены. Затем вы возвращаете представление в блоке catch, даже не указывая, что такое ошибка, и еще больше запутывает пользователя.

Удалите try/catch блоки и пусть рамки справиться с этим, пока вы не поймете больше об обработке ошибок (страница ошибок по умолчанию будет отображаться) и изменить код

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Create(SkillSetsModel model) 
{ 
    if (!ModelState.IsValid) 
    { 
    // Return the view so the user can correct errors 
    ViewBag.Campaign = ... // as per the GET method 
    return View(model); 
    } 
    db.SkillSets.Add(ss); 
    db.SaveChanges(); 
    return RedirectToAction("Index"); 
} 

Наконец, я рекомендовал бы использовать вид модели, представляют только данные, которые вы хотите отобразить/редактировать в представлении (см. What is ViewModel in MVC?). Для вашего Create просмотра он не будет включать свойства для IDSkillset (объект еще не существует в базе данных) или PersonSkills, но будет включать в себя свойство IEnumerable<SelectListItem> Campaign (хотя CategoryList кажется более подходящим) вместе с атрибутами отображения и проверки (a [Display] атрибут в модели данных не подходит, так как это зависит от вида)

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