【发布时间】:2016-05-06 22:46:09
【问题描述】:
我有以下两个模型(剥离到相关部分):
模型\Department.cs:
public class DepartmentValidator : AbstractValidator<Department> {
public DepartmentValidator() {
RuleFor(d => d.Name)
.NotEmpty().WithMessage("You must specify a name.")
.Length(0, 256).WithMessage("The name cannot exceed 256 characters in length.");
}
}
[Validator(typeof(DepartmentValidator))]
public class Department {
public int Id { get; set; }
[Column(TypeName = "nvarchar")]
[MaxLength(256)]
public string Name { get; set; }
}
模型\FacultyMember.cs:
public class FacultyValidator : AbstractValidator<FacultyMember> {
public FacultyValidator() {
RuleFor(f => f.Name)
.NotEmpty().WithMessage("You must specify a name.")
.Length(0, 64).WithMessage("The name cannot exceed 64 characters in length.");
}
}
[Validator(typeof(FacultyValidator))]
public class FacultyMember {
public int Id { get; set; }
[Column(TypeName = "nvarchar")]
[MaxLength(64)]
public string Name { get; set; }
public virtual ICollection<Department> Departments { get; set; }
public FacultyMember() {
Departments = new HashSet<Department>();
}
}
我有以下控制器代码:
控制器\FacultyController.cs:
// GET: Faculty/Create
public ActionResult Create() {
// Get Departments.
var departmentList = db.Departments.ToList().Select(department => new SelectListItem {
Value = department.Id.ToString(),
Text = department.Name
}).ToList();
ViewBag.DepartmentList = departmentList;
var facultyMember = new FacultyMember();
facultyMember.Departments.Add(new Department()); // Create a single dropdown for a department to start out.
return View(facultyMember);
}
// POST: Faculty/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,Name,Departments")] FacultyMember facultyMember) {
// Get Departments.
var departmentList = db.Departments.ToList().Select(department => new SelectListItem {
Value = department.Id.ToString(),
Text = department.Name
}).ToList();
ViewBag.DepartmentList = departmentList;
if (!ModelState.IsValid) { // Problem here...
return View(facultyMember);
}
db.Faculty.Add(facultyMember);
db.SaveChanges();
return RedirectToAction("Index");
}
Views\Faculty\Create.cshtml:
...
<div class="form-group">
@Html.LabelFor(model => model.Departments, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Departments, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Departments, "", new { @class = "text-danger" })
</div>
</div>
...
Views\Shared\EditorTemplates\Department.cshtml:
@model MyProject.Models.Department
@Html.DropDownListFor(model => model.Id, ViewBag.DepartmentList as IEnumerable<SelectListItem>, "Select...", new { @class = "form-control" })
所以,当我导航到创建教师页面时,一切都正常显示; “部门”字段有一个下拉列表,其中包含我数据库中的部门。但是,在提交表单后,我的模型状态无效(请参阅上面代码中的注释)。经过进一步检查,FluentValidation 似乎吐出了一个错误,因为我的“名称”字段为空。这正是我创建/编辑部门时应该做的事情,但是对于教职员工的下拉列表,它不应该验证整个部门,不是吗?正如我所指定的,下拉列表唯一发回的就是 ID。
此下拉列表发送的唯一内容是正确接收的部门 ID。那么,我需要做什么才能完成这项工作?我的目标是拥有一组动态的下拉列表,每个下拉列表都填充了数据库中的现有部门。类似于this 的例子。
如果还有什么需要解释的,请告诉我。
【问题讨论】:
-
您应该为下拉列表使用带有属性
int SelectedDepartment的视图模型,而不是绑定到复杂对象。您的下拉列表不会回发Department.Name的值,因此ModelState将始终无效。 -
感谢您的快速回复。我需要创建一个新类来表示这个 ViewModel,对吗?在其中,我只需输入我需要的所有数据,包括常规教员字段和选定的部门 ID/列表?我将如何处理动态数量的部门?我的 ViewModel 是否只有一个类似于我的常规模型的 ICollection,然后我遍历它们并在数据回发时对每个模型执行 Find(id)?
-
您是要为
FacultMember选择多个Department(即使用ListBox 或CheckedListBox),还是使用DropDownList 为FacultyMember选择一个Department? -
我希望每位教员都属于一个或多个系,具体取决于所讨论的教员是全职还是兼职(我在 FacultyMember 模型中拥有的枚举属性)。所以,我的服务器端验证会检查教员是否是全职的。如果是这样,他们只能有一个部门。否则,他们至少可以拥有一个。我可能会使用某种具有多选属性的列表框,然后在服务器端验证所选项目的数量。
-
在这种情况下,您的视图模型将需要 2 个“选择”属性 -
int SelectedDepartment和int[] SelectedDepartments和IEnumerable<SelectListItem>DepartmentList` 用于选项。然后根据您的enum属性的值,您将显示一个下拉列表或一个列表框来选择一个(如果是全职)或一个或多个(如果不是全职)。您可以根据枚举的值应用RequiredIf验证。
标签: c# model asp.net-mvc-5 fluentvalidation