我在DropDownList中的回发问题。我正在尝试创建一个允许用户创建新技能组的页面,但技能组与技能类别相关联,因此我使用DropDownList以便用户可以选择技能组所属的类别,但我收到此异常:
System.Web.Mvc.dll中发生了'System.ArgumentNullException'类型的异常,但未在用户代码中处理
附加信息:值不能为空。
这是我的创建控制器:
// 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方法的Get部分,因为正在填充DropDownList,所以在view或Post方法中似乎存在问题。
答案 0 :(得分:2)
错误的原因是您将下拉列表绑定到名为Campaign
的属性,但您的模型不包含具有该名称的属性。根据相关标签和验证消息,您要将所选值分配给属性IDCategory
,因此在视图中需要
@Html.DropDownListFor(m => m.IDCategory, (IEnumerable<SelectListItem>)ViewBag.Campaign)
请注意,ViewBag
属性已经IEnumerable<SelectListItem>
,因此使用new SelectList(ViewBag.Campaign, "Value", "Text")
只是毫无意义的额外开销(您从现有的IEnumerable<SelectListItem>
构建新的Category
但是,您的代码还有许多其他错误。
在GET方法中,您只选择.Distinct()
的ID属性,然后使用Category
。如果您的ID属性不是唯一的,则表明您的数据库结构存在问题。您还只在视图中显示ID值,这对用户来说不太合适。假设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
而不是ModelState
这一事实也表明您的数据库/模型设计存在问题。
在POST方法中,如果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");
}
块并让框架处理此问题,直到您了解有关处理错误的更多信息(将显示默认错误页面)并将代码更改为
Create
最后,我建议使用仅代表您要在视图中显示/编辑的数据的视图模型(请参阅What is ViewModel in MVC?)。对于IDSkillset
视图,它不会包含PersonSkills
(该对象尚未存在于数据库中)或IEnumerable<SelectListItem> Campaign
的属性,但会包含属性CategoryList
(尽管[Display]
似乎是一个更合适的名称)以及显示和验证属性(数据模型中的{{1}}属性不合适,因为它是特定于视图的)
答案 1 :(得分: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!