ModelState.IsValid 包含导航 属性。总是假的。 (仅限net-6.0) 怎么弄成真?
ModelState.IsValid includes a navigation property. Always false. (only net-6.0) How to get true?
这是 dotnet 上的示例。 github.com/dotnet... 我在 net-6.0 版本上工作
验证检查的结果为 false,因为 class 的导航属性参与了验证。
我在 net-5.0 上实现了一个简单的实验——导航属性没有反映在结果中。但是,也许我错了。
如何正确解决这个问题?
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }
[StringLength(50, MinimumLength = 3)]
public string Title { get; set; }
[Range(0, 5)]
public int Credits { get; set; }
public int DepartmentID { get; set; }
public Department Department { get; set; }
public ICollection<Enrollment> Enrollments { get; set; }
public ICollection<CourseAssignment> CourseAssignments { get; set; }
}
CoursesController.cs
// POST: Courses/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
[Bind("CourseID,Credits,DepartmentID,Title")] Course course)
{
if (ModelState.IsValid)
{
_context.Add(course);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);
}
验证结果
不确定这是否回答了您的问题。但建议您 创建一个 Data Transfer Object (DTO) class 而不是直接使用(生成的)数据库对象 class.
DTO class 是根据 API 预期接收的值(架构)设计的。并且这个 DTO class 还将用于执行 first-level 数据验证,例如 Required、Range 等(不涉及对数据库的验证)
public class CreateCourseDto
{
[Display(Name = "Number")]
public int CourseID { get; set; }
[StringLength(50, MinimumLength = 3)]
public string Title { get; set; }
[Range(0, 5)]
public int Credits { get; set; }
public int DepartmentID { get; set; }
}
然后只将DTO 中的值绑定到真正的DB 对象。手动 bind/assign 值或应用 tool/library 例如 AutoMapper.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
[Bind("CourseID,Credits,DepartmentID,Title")] CreateCourseDto course)
{
if (ModelState.IsValid)
{
// Map received course value to DB object
Course _course = new Course
{
CourseID = course.CourseID,
Title = course.Title,
Credits = course.Credits,
DepartmentID = course.DepartmentID
};
_context.Add(_course);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);
}
我认为问题出在新的可空功能 net6。我强烈建议您将其删除或在项目属性中发表评论
<!--<Nullable>enable</Nullable>-->
这是一个非常愚蠢的功能。在生命结束之前,您必须将所有属性标记为可为空。
public ICollection<CourseAssignment>? CourseAssignments { get; set; }
恕我直言,从不在控制器操作参数中使用绑定。你总是会遇到问题。它只在剃须刀页面中有用,但在非常非常罕见的情况下。并在极少数情况下使用 Dto。当我必须从连接创建最多的属性时,我通常只将 Dto 用于 select。
这是 dotnet 上的示例。 github.com/dotnet... 我在 net-6.0 版本上工作
验证检查的结果为 false,因为 class 的导航属性参与了验证。 我在 net-5.0 上实现了一个简单的实验——导航属性没有反映在结果中。但是,也许我错了。
如何正确解决这个问题?
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }
[StringLength(50, MinimumLength = 3)]
public string Title { get; set; }
[Range(0, 5)]
public int Credits { get; set; }
public int DepartmentID { get; set; }
public Department Department { get; set; }
public ICollection<Enrollment> Enrollments { get; set; }
public ICollection<CourseAssignment> CourseAssignments { get; set; }
}
CoursesController.cs
// POST: Courses/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
[Bind("CourseID,Credits,DepartmentID,Title")] Course course)
{
if (ModelState.IsValid)
{
_context.Add(course);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);
}
验证结果
不确定这是否回答了您的问题。但建议您 创建一个 Data Transfer Object (DTO) class 而不是直接使用(生成的)数据库对象 class.
DTO class 是根据 API 预期接收的值(架构)设计的。并且这个 DTO class 还将用于执行 first-level 数据验证,例如 Required、Range 等(不涉及对数据库的验证)
public class CreateCourseDto
{
[Display(Name = "Number")]
public int CourseID { get; set; }
[StringLength(50, MinimumLength = 3)]
public string Title { get; set; }
[Range(0, 5)]
public int Credits { get; set; }
public int DepartmentID { get; set; }
}
然后只将DTO 中的值绑定到真正的DB 对象。手动 bind/assign 值或应用 tool/library 例如 AutoMapper.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
[Bind("CourseID,Credits,DepartmentID,Title")] CreateCourseDto course)
{
if (ModelState.IsValid)
{
// Map received course value to DB object
Course _course = new Course
{
CourseID = course.CourseID,
Title = course.Title,
Credits = course.Credits,
DepartmentID = course.DepartmentID
};
_context.Add(_course);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);
}
我认为问题出在新的可空功能 net6。我强烈建议您将其删除或在项目属性中发表评论
<!--<Nullable>enable</Nullable>-->
这是一个非常愚蠢的功能。在生命结束之前,您必须将所有属性标记为可为空。
public ICollection<CourseAssignment>? CourseAssignments { get; set; }
恕我直言,从不在控制器操作参数中使用绑定。你总是会遇到问题。它只在剃须刀页面中有用,但在非常非常罕见的情况下。并在极少数情况下使用 Dto。当我必须从连接创建最多的属性时,我通常只将 Dto 用于 select。