远程验证显示错误消息但仍让表单提交并保存在数据库 MVC 5
Remote validation shows error message but still lets the form submit and saves in database MVC 5
情况是,Student Reg 的组合。编号和Select课程始终是独一无二的。
选择之前保存在数据库中的组合后,预期结果是,
第一个预期结果:
将出现错误消息“Selected 学生已经参加了这门课程”。
第二个预期结果:
它将阻止提交表单,直到选择了之前未保存在数据库中的不同组合。
当前结果:
第一个预期结果运行良好:
但是,第二个预期结果不起作用。即提交表单并保存之前已经保存在数据库中的组合。
能否给个解决方案,我可以得到第二个预期结果?
提前致谢。
为了便于阅读,我排除了所有代码,html 以及与姓名、电子邮件和部门相关的脚本。
这是我的模型,
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Web.Mvc;
namespace UniversityApplication.Models
{
public class CourseStudent
{
[Required]
[DisplayName("Student Reg. No.")]
public string CourseStudentRegNo { get; set; }
[Required]
[Remote("IsCourseNameExists", "CourseStudents", AdditionalFields = "CourseStudentRegNo", ErrorMessage = "Selected Student has taken this course already.")]
[DisplayName("Select Course")]
public string CourseStudentCourse { get; set; }
[Required]
[DisplayName("Date")]
[DataType(DataType.Date)]
public DateTime CourseStudentRegDate { get; set; }
}
}
这是我的控制器,
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using UniversityApplication.Context;
using UniversityApplication.Models;
namespace UniversityApplication.Controllers
{
public class CourseStudentsController : Controller
{
private ApplicationContext db = new ApplicationContext();
public ActionResult StudentToCourse()
{
GenerateDropDownValue();
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult StudentToCourse([Bind(Include = "CourseStudentID,CourseStudentRegNo,CourseStudentName,CourseStudentEmail,CourseStudentDepartmentCode,CourseStudentCourse,CourseStudentRegDate")] CourseStudent courseStudent)
{
GenerateDropDownValue();
if (ModelState.IsValid)
{
db.CoursesStudents.Add(courseStudent);
db.SaveChanges();
ModelState.Clear();
return View();
}
ModelState.Clear();
return View();
}
private void GenerateDropDownValue()
{
List<Student> allRegisteredStudents = new List<Student>();
List<SelectListItem> students = new List<SelectListItem>();
List<Course> allCourses = new List<Course>();
string studentName = "";
string studentEmail = "";
string studentDepartment = "";
using (ApplicationContext db = new ApplicationContext())
{
allRegisteredStudents = db.Students.OrderBy(a => a.StudentRegNo).ToList();
}
foreach (var student in allRegisteredStudents)
{
students.Add(
new SelectListItem()
{
Value = student.StudentRegNo,
Text = student.StudentRegNo
}
);
}
ViewBag.Students = students;
ViewBag.CourseCode = new SelectList(allCourses, "CourseCode", "CourseName");
ViewBag.StudentName = studentName;
ViewBag.StudentEmail = studentEmail;
ViewBag.StudentDepartment = studentDepartment;
}
public JsonResult IsCourseNameExists(string CourseStudentCourse, string CourseStudentRegNo)
{
return Json(!db.CoursesStudents.Any(x => x.CourseStudentCourse == CourseStudentCourse && x.CourseStudentRegNo == CourseStudentRegNo), JsonRequestBehavior.AllowGet);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
这是我的观点,
@model UniversityApplication.Models.CourseStudent
@{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>CourseStudent</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.CourseStudentRegNo, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.CourseStudentRegNo, @ViewBag.Students as SelectList, "Select Student", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.CourseStudentRegNo, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CourseStudentCourse, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.CourseStudentCourse, @ViewBag.CourseCode as SelectList, "Select Course", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.CourseStudentCourse, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CourseStudentRegDate, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.CourseStudentRegDate, new { @class = "date form-control", @readonly = "true" })
@Html.ValidationMessageFor(model => model.CourseStudentRegDate, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Enroll" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
<link href="~/Content/themes/base/all.css" rel="stylesheet" />
@section Scripts {
<script src="~/Scripts/jquery.validate.date.js"></script>
@Scripts.Render("~/bundles/jqueryui")
@Styles.Render("~/Content/cssjqryUi")
@Scripts.Render("~/bundles/jqueryval")
<script>
$(document).ready(function () {
$('.date').datepicker({ dateFormat: "dd/mm/yy" });
});
</script>
}
而不是通过 JsonResult 方法使用自定义远程验证 IsCourseNameExists
我建议通过 自定义数据注释 .
实现您的验证
参考这个link关于如何通过数据注释创建自定义验证:Custom Validation Data Annotation Attribute
如果验证不成功,则使用此方法,您将得到无效模型状态,您无需担心该错误。它还使您的架构更加安全。
此外, 作为最佳实践,您还应该在控制器的服务器端进行相同的检查(您在 IsCourseNameExists
方法中进行的检查),就在您保存到数据库之前。 注意:如果您只执行此检查,即使您的要求得到满足。
已解决
我错过了添加
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
我的 cshtml 文件之上的上述脚本。
看起来,
@model UniversityApplication.Models.CourseStudent
@{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
//Rest codes
情况是,Student Reg 的组合。编号和Select课程始终是独一无二的。
选择之前保存在数据库中的组合后,预期结果是,
第一个预期结果:
将出现错误消息“Selected 学生已经参加了这门课程”。
第二个预期结果:
它将阻止提交表单,直到选择了之前未保存在数据库中的不同组合。
当前结果:
第一个预期结果运行良好:
但是,第二个预期结果不起作用。即提交表单并保存之前已经保存在数据库中的组合。
能否给个解决方案,我可以得到第二个预期结果?
提前致谢。
为了便于阅读,我排除了所有代码,html 以及与姓名、电子邮件和部门相关的脚本。
这是我的模型,
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Web.Mvc;
namespace UniversityApplication.Models
{
public class CourseStudent
{
[Required]
[DisplayName("Student Reg. No.")]
public string CourseStudentRegNo { get; set; }
[Required]
[Remote("IsCourseNameExists", "CourseStudents", AdditionalFields = "CourseStudentRegNo", ErrorMessage = "Selected Student has taken this course already.")]
[DisplayName("Select Course")]
public string CourseStudentCourse { get; set; }
[Required]
[DisplayName("Date")]
[DataType(DataType.Date)]
public DateTime CourseStudentRegDate { get; set; }
}
}
这是我的控制器,
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using UniversityApplication.Context;
using UniversityApplication.Models;
namespace UniversityApplication.Controllers
{
public class CourseStudentsController : Controller
{
private ApplicationContext db = new ApplicationContext();
public ActionResult StudentToCourse()
{
GenerateDropDownValue();
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult StudentToCourse([Bind(Include = "CourseStudentID,CourseStudentRegNo,CourseStudentName,CourseStudentEmail,CourseStudentDepartmentCode,CourseStudentCourse,CourseStudentRegDate")] CourseStudent courseStudent)
{
GenerateDropDownValue();
if (ModelState.IsValid)
{
db.CoursesStudents.Add(courseStudent);
db.SaveChanges();
ModelState.Clear();
return View();
}
ModelState.Clear();
return View();
}
private void GenerateDropDownValue()
{
List<Student> allRegisteredStudents = new List<Student>();
List<SelectListItem> students = new List<SelectListItem>();
List<Course> allCourses = new List<Course>();
string studentName = "";
string studentEmail = "";
string studentDepartment = "";
using (ApplicationContext db = new ApplicationContext())
{
allRegisteredStudents = db.Students.OrderBy(a => a.StudentRegNo).ToList();
}
foreach (var student in allRegisteredStudents)
{
students.Add(
new SelectListItem()
{
Value = student.StudentRegNo,
Text = student.StudentRegNo
}
);
}
ViewBag.Students = students;
ViewBag.CourseCode = new SelectList(allCourses, "CourseCode", "CourseName");
ViewBag.StudentName = studentName;
ViewBag.StudentEmail = studentEmail;
ViewBag.StudentDepartment = studentDepartment;
}
public JsonResult IsCourseNameExists(string CourseStudentCourse, string CourseStudentRegNo)
{
return Json(!db.CoursesStudents.Any(x => x.CourseStudentCourse == CourseStudentCourse && x.CourseStudentRegNo == CourseStudentRegNo), JsonRequestBehavior.AllowGet);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
这是我的观点,
@model UniversityApplication.Models.CourseStudent
@{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>CourseStudent</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.CourseStudentRegNo, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.CourseStudentRegNo, @ViewBag.Students as SelectList, "Select Student", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.CourseStudentRegNo, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CourseStudentCourse, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.CourseStudentCourse, @ViewBag.CourseCode as SelectList, "Select Course", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.CourseStudentCourse, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CourseStudentRegDate, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.CourseStudentRegDate, new { @class = "date form-control", @readonly = "true" })
@Html.ValidationMessageFor(model => model.CourseStudentRegDate, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Enroll" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
<link href="~/Content/themes/base/all.css" rel="stylesheet" />
@section Scripts {
<script src="~/Scripts/jquery.validate.date.js"></script>
@Scripts.Render("~/bundles/jqueryui")
@Styles.Render("~/Content/cssjqryUi")
@Scripts.Render("~/bundles/jqueryval")
<script>
$(document).ready(function () {
$('.date').datepicker({ dateFormat: "dd/mm/yy" });
});
</script>
}
而不是通过 JsonResult 方法使用自定义远程验证 IsCourseNameExists
我建议通过 自定义数据注释 .
参考这个link关于如何通过数据注释创建自定义验证:Custom Validation Data Annotation Attribute
如果验证不成功,则使用此方法,您将得到无效模型状态,您无需担心该错误。它还使您的架构更加安全。
此外, 作为最佳实践,您还应该在控制器的服务器端进行相同的检查(您在 IsCourseNameExists
方法中进行的检查),就在您保存到数据库之前。 注意:如果您只执行此检查,即使您的要求得到满足。
已解决
我错过了添加
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
我的 cshtml 文件之上的上述脚本。
看起来,
@model UniversityApplication.Models.CourseStudent
@{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
//Rest codes