ASP.NET MVC Core 3.1 中的条件客户端验证

Conditional client side validation in ASP.NET MVC Core 3.1

我想在 ASP.NET MVC Core 3.1 中进行条件验证。我已经编写了自定义验证,它在服务器端验证中运行良好,但我无法执行客户端验证。在我的示例应用程序中,有一个 Salary 文本框,只有在 Roles 下拉列表中选择 Role=Teacher 时才需要它。能否请您在客户端验证部分帮助我,这是完整的示例代码。

员工模型class

public class Employee
    {
        public int Id { get; set; }

        [Required(ErrorMessage = "Please enter name")]
        public string Name { get; set; }

        [Required(ErrorMessage = "Please enter email")]
        [EmailAddress]
        public string Email { get; set; }

        [Required(ErrorMessage = "Please enter  role")]
        [EnumDataType(typeof(Roles))]
        public Roles? Role { get; set; }

        [Required(ErrorMessage = "Please Enter Hire Date")]
        [Display(Name = "Hire Date")]
        public DateTime? HireDate { get; set; }

        [RequiredIf("Role", Roles.Teacher, ErrorMessage = "Please enter salary")]
        public int? Salary { get; set; }
    }

角色枚举

 public enum Roles
    {
        Student = 1,
        Teacher = 2,
        Assistant = 3        
    }

RequiredIfAttribute 自定义验证class

public class RequiredIfAttribute : ValidationAttribute, IClientModelValidator
    {
        public string PropertyName { get; set; }
        public object Value { get; set; }

        public RequiredIfAttribute(string propertyName, object value, string errorMessage = "")
        {
            PropertyName = propertyName;
            ErrorMessage = errorMessage;
            Value = value;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var instance = validationContext.ObjectInstance;
            var type = instance.GetType();
            var proprtyvalue = type.GetProperty(PropertyName).GetValue(instance, null);
            if (proprtyvalue != null)
            {
                if (proprtyvalue.ToString() == Value.ToString() && value == null)
                {
                    return new ValidationResult(ErrorMessage);
                }
            }     
            return ValidationResult.Success;
        }

        public void AddValidation(ClientModelValidationContext context)
        {
            context.Attributes.Add("data-val", "true");
            context.Attributes.Add("data-val-country", ErrorMessage);
        }
    }

UI

的索引视图
@model ASPNETCoreValidations.Models.Employee
@using ASPNETCoreValidations.Models.enums
@{
    ViewBag.Title = "Index";
}

<h1>Create</h1>

<h4>Business unit</h4>
<hr />
<div class="container">
    <form asp-action="Index">

        <div asp-validation-summary="All" class="text-danger"></div>

        <div class="form-group">
            <div class="row">
                <div class="col-md-6">
                    <label asp-for="Name" class="control-label"></label>
                    <input asp-for="Name" class="form-control" />
                    <span asp-validation-for="Name" class="text-danger"></span>
                </div>
                <div class="col-md-6">
                    <label asp-for="Email" class="control-label"></label>
                    <input asp-for="Email" class="form-control" />
                    <span asp-validation-for="Email" class="text-danger"></span>
                </div>
            </div>
        </div>


        <div class="form-group">
            <div class="row">
                <div class="col-md-6">
                    <label asp-for="Role" class="control-label"></label>
                    <select asp-for="Role" class="form-control" asp-items="Html.GetEnumSelectList<Roles>()">
                        <option value="">Select Department</option>
                    </select>
                    <span asp-validation-for="Role" class="text-danger"></span>
                </div>
                <div class="col-md-6">
                    <label asp-for="HireDate" class="control-label"></label>
                    <input asp-for="HireDate" class="form-control" />
                    <span asp-validation-for="HireDate" class="text-danger"></span>
                </div>
            </div>
        </div>

        <div class="form-group">
            <div class="row">
                <div class="col-md-6">
                    <label asp-for="Salary" class="control-label"></label>
                    <input asp-for="Salary" class="form-control" />
                    <span asp-validation-for="Salary" class="text-danger"></span>
                </div>
            </div>
        </div>

        <div class="form-group">
            <input type="submit" value="Create" class="btn btn-primary" />
        </div>
    </form>
</div>


@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    <script src="~/js/RequiredIfValidate.js"></script>
}

Jquery 用于客户端验证

jQuery.validator.addMethod("requiredif",
    function (value, element, param) {    
        
      // I need help here. This method never gets executed and I don't know how to implement validation here ...
      // return true or false depending on the condition
    });

jQuery.validator.unobtrusive.adapters.addBool("requiredif");

索引操作

        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Index(Employee employee)
        {
            if (ModelState.IsValid)
            {
                RedirectToAction("Index");
            }

            return View();
        }

根据您的描述,我建议您可以在 RequiredIfAttribute AddValidation 属性中添加一个 属性 以将角色添加到输入工资中。

那么我建议您可以尝试使用以下验证不显眼的脚本:

RequiredIfAttribute :

public class RequiredIfAttribute : ValidationAttribute, IClientModelValidator
{
    public string PropertyName { get; set; }
    public object Value { get; set; }

    public RequiredIfAttribute(string propertyName, object value, string errorMessage = "")
    {
        PropertyName = propertyName;
        ErrorMessage = errorMessage;
        Value = value;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var instance = validationContext.ObjectInstance;
        var type = instance.GetType();
        var proprtyvalue = type.GetProperty(PropertyName).GetValue(instance, null);
        if (proprtyvalue != null)
        {
            if (proprtyvalue.ToString() == Value.ToString() && value == null)
            {
                return new ValidationResult(ErrorMessage);
            }
        }
        return ValidationResult.Success;
    }

    public void AddValidation(ClientModelValidationContext context)
    {
        context.Attributes.Add("data-val", "true");
        context.Attributes.Add("data-val-country", ErrorMessage);
        context.Attributes.Add("data-val-country-role", Value.ToString());
    }
}

脚本:

@section Scripts{
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/jquery.validate.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>

    <script>

        $.validator.addMethod('country', function (value, element, params) {
            var genre = $(params[0]).val(), role = params[1], salar = value;

            var selecttest = $("#Role option:selected").text();
 
            if (selecttest == role) {
                if (value.length == 0) {
                    console.log("selecttest == role value = null");
                    return false;

                } else {
                    console.log("selecttest == role value != null");
                    return true;
                }
            } else {
                console.log("selecttest != role");
                return true;
            }



        });

        $.validator.unobtrusive.adapters.add('country', ['role'], function (options) {
            var element = $(options.form).find('select#Salary')[0];

            options.rules['country'] = [element, options.params['role']];
            options.messages['country'] = options.message;
        });
    </script>

}

结果: