@Html.DropDownListFor 没有回发给控制器

@Html.DropDownListFor not posting back to controller

我是第一次使用 @Html.DropDownListFor。代码如下。

型号:

class Student
{
    [Required]
    [Display(Name = "Name")]
    public string Name { get; set; }

    [Required]
    [Display(Name = "Roll Number")]
    public string RollNumber { get; set; }

    [Required]
    [Display(Name = "ClassId")]
    public int ClassId { get; set; }

}

class Class
{
    [Required]
    [Display(Name = "ClassId")]
    public string RollNumber { get; set; }

    [Required]
    [Display(Name = "ClassName")]
    public string RollNumber { get; set; }
}

控制器:

public ActionResult Create()
{
    Student student = new BusinessEntities.Student();
    List<Class> classes = GetAllClasses();
    ViewBag.ClassId = new SelectList(classes, "ClassId", "ClassName");
    return View(student);
}

[HttpPost]
public ActionResult Create(BusinessEntities.Student student)
{
   if (ModelState.IsValid)
   {
      //Integer has 0 by default. But in our case if it contains 0, 
      //means no class selected by user
      if(student.ClassId==0)
      {
        ModelState.AddModelError("ClassId", "Select Class to Enroll in");
        return View(student);
      }
    }
}

学生创建视图:

<form  method="post">
    Select Class : 
    @Html.DropDownListFor(Model=>Model.ClassId,ViewBag.ClassId as IEnumerable<SelectListItem>, "ClassId","ClassName")
    @Html.ValidationMessageFor(Model => Model.ClassId)
    <input type="submit" value="Submit" />
</form>

错误信息:

The ViewData item that has the key 'ClassId' is of type 'System.Collections.Generic.List`1[[BusinessEntities.Class, BusinessEntities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' but must be of type 'IEnumerable'.

我希望 ClassId of Student 在发回 Controller 时自动绑定和填充。请帮我摆脱它。 谢谢。

您需要给 SelectList 一个不同于 属性 绑定的名称(比如)

ViewBag.ClassList = new SelectList(classes, "ClassId", "ClassName");` 

然后

@Html.DropDownListFor(m => m.ClassId, ViewBag.ClassList as IEnumerable<SelectListItem>)

然后确保如果您 return 视图(例如,如果 ModelState 无效),则您重新填充 SelectList (就像您在 GET 方法中所做的那样)。目前当你 return 视图时,它是 null 导致错误,因为如果第二个参数是 null 后备是助手期望第一个参数是 IEnumerable<SelectListItem>(但它不是 - 它的类型 int

旁注:不要使用 Model => Model.XXX(大写 M)和您当前使用的 DropDownistFor() 作为两个没有意义的参数。 "ClassId" 将添加一个标签选项 <option value="">ClassId</option> 而最后一个 ,"ClassName" 不会做任何事情。

编辑

此外,您的

if(student.ClassId==0)
{
    ModelState.AddModelError("ClassId", "Select Class to Enroll in");
    return View(student);
}

有点无意义。 student.ClassId 永远不会是 0,除非你的 GetAllClasses() 中的一项有 ClassId = 0。你应该使用

[Required(ErrorMessage = "Select Class to Enroll in")] // add error message here
public int ClassId { get; set; }

并在视图中

@Html.DropDownListFor(m => m.ClassId, ViewBag.ClassList as IEnumerable<SelectListItem>, "--please select--")

这将创建值为 null 的第一个选项。如果选择此选项,则 DefaultModelBinder 将尝试设置失败的 ClassId = null 的值(因为 typeof int 不能是 null)和 ModelState添加了错误,ModelState 变得无效。

POST方法中的

[HttpPost]
public ActionResult Create(BusinessEntities.Student student)
{
  if (!ModelSTate.IsValid)
  {
    ViewBag.ClassList = // repopulate select list
    return View(student);
  }
  // Save and redirect
}