简体   繁体   中英

Conditional client side validation in ASP.NET MVC Core 3.1

I want to make conditional validation in ASP.NET MVC Core 3.1. I have written custom validation and it works fine in server-side validation but I am unable to perform client-side validation. In my sample application, there is a Salary textbox, which is only required if the Role=Teacher is selected in the Roles dropdown. Could you please help me in the client-side validation part and here is the complete sample code.

Employee model 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; }
    }

Roles enum

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

RequiredIfAttribute custom validation 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);
        }
    }

Index view for the 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 for client-side validation

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");

Index action

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

            return View();
        }

According to your description, I suggest you could add a property in the RequiredIfAttribute AddValidation attribute to add the role to the input salary.

Then I suggest you could try to use below validation unobtrusive scripts:

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());
    }
}

Scripts:

@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>

}

Result:

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM