远程验证显示错误消息但仍让表单提交并保存在数据库 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