skip to Main Content

I created a simple custom validation. It works ok on server side (with ModelState.IsValid), but I would like to make it run on client side.

Regular validators such as Required and RegularExpression are working great on client side.

My custom attribute

public class UniqueSkuAttribute : ValidationAttribute
{
    public override bool IsValid(object? value)
    {
        if (value == null)
        {
            return false; 
        }

        // IsValueExist() is my own method
        return IsValueExist(value.ToString());
    }
}

My property

[Required(ErrorMessage = "Value is needed")]
[UniqueSku(ErrorMessage = "Value already exist")]
[RegularExpression("^\d{11}[a-zA-Z]{2}$", ErrorMessage = "Value in template of: 01234567890xx")]
public string SKU { get; set; }

The view that use that property

<div class="form-floating mb-3 mt-3">
    <input asp-for="SKU" maxlength="13" class="form-control" placeholder="SKU">
    <label asp-for="SKU">Project SKU</label>
    <span asp-validation-for="SKU" class="text-danger"></span>
</div>

Additionally, I added of course the _ValidationScriptsPartial.cshtml file as partial to each view page.

There is a reason why custom validator is not working on client side?

2

Answers


  1. Basically, you need to implement this in your client side.

    For example, lets say you have a model like below :

    public class TestClass
    {
        [Required]
        public string Name { get; set; }
    
        [Required]
        [EmailAddress] // You can even pass your own regex's here
        public string Email { get; set; }
    }
    

    you can refer it in you client side template like below :

    <input class="form-control" asp-for="Input.Name">
          <label asp-for="Input.Name"></label>
          <span class="text-danger field-validation-valid" asp-validation-for="Input.Name"></span>
    <input class="form-control" asp-for="Input.Email">
          <label asp-for="Input.Email"></label>
          <span class="text-danger field-validation-valid" asp-validation-for="Input.Email"></span>
    

    Look for the attribute asp-validation-for attribute in the template which does the magic on the client side for pairing up the validation in your model class into the template.

    As a reference please refer the link here.

    Login or Signup to reply.
  2. The logic of IsValueExist needs to be replicated on the client side and added to the unobtrusive validation library for this to work, something like this:

    C#

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
    public class UniqueSkuAttribute : ValidationAttribute, IClientModelValidator
    {
        public void AddValidation(ClientModelValidationContext context)
            {
                MergeAttribute(context.Attributes, "data-val", "true");
                var errorMsg = FormatErrorMessage(context.ModelMetadata.GetDisplayName());
                MergeAttribute(context.Attributes, "data-val-uniquesku", errorMsg);
            }
        public override bool IsValid(object? value)
        {
            if (value == null)
            {
                return false;
            }
    
            // IsValueExist() is my own method
            return IsValueExist(value.ToString());
        }
    
          private bool MergeAttribute(
                      IDictionary<string, string> attributes,
                      string key,
                      string value)
            {
                if (attributes.ContainsKey(key))
                {
                    return false;
                }
                attributes.Add(key, value);
                return true;
            }
    }
    

    JS

    $.validator.addMethod("uniquesku",
        function (value, element, parameters) {
            // Here goes your IsValueExist logic that returns bool
        });
    
    $.validator.unobtrusive.adapters.add("uniquesku", [], function (options) {
        options.rules.uniquesku = {};
        options.messages["uniquesku"] = options.message;
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search