45

In previous versions of the MVC framework custom validation would be achieved through implementing IClientValidatable and the GetClientValidationRules method.

However in ASP.Net Core MVC we do not have this interface, although we do have IClientModelValidator which a defining a very similar method. The implementation of which never gets called however.

So - how do we implement client-side validation for a custom attribute in ASP.NET Core MVC?

1 Answer 1

66

The IClientModelValidator is in fact the right interface. I've made a contrived sample implementation below.

Attribute

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class CannotBeRedAttribute : ValidationAttribute, IClientModelValidator
{
    public override bool IsValid(object value)
    {
        var message = value as string;
        return message?.ToUpper() == "RED";
    }

    public void AddValidation(ClientModelValidationContext context)
    {
        MergeAttribute(context.Attributes, "data-val", "true");
        var errorMessage = FormatErrorMessage(context.ModelMetadata.GetDisplayName());
        MergeAttribute(context.Attributes, "data-val-cannotbered", errorMessage);
    }

    private bool MergeAttribute(
        IDictionary<string, string> attributes,
        string key,
        string value)
    {
        if (attributes.ContainsKey(key))
        {
            return false;
        }
        attributes.Add(key, value);
        return true;
    }
}

Model

public class ContactModel
{
    [CannotBeRed(ErrorMessage = "Red is not allowed!")]
    public string Message { get; set; }
}

View

@model WebApplication.Models.ContactModel

<form asp-action="Contact" method="post">
    <label asp-for="Message"></label>
    <input asp-for="Message" />
    <span asp-validation-for="Message"></span>
    <input type="submit" value="Save" />
</form>

@section scripts {
    <script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
    <script>
        $.validator.addMethod("cannotbered",
            function (value, element, parameters) {
                return value.toUpperCase() !== "RED";
            });

        $.validator.unobtrusive.adapters.add("cannotbered", [], function (options) {
            options.rules.cannotbered = {};
            options.messages["cannotbered"] = options.message;
        });
    </script>
}
Sign up to request clarification or add additional context in comments.

11 Comments

I have done exactly as shown by you in the example. but its not working, it is not showing the message returned by GetClientValidationRules. Instead showing the default required message ?
@Rohit The custom attribute in my example will only show an error if you type in the word "red" in the input box.
I have written a class from where I am getting custom error messages which I want to use in 'GetClientValidationRules' method. If I do so like yield return new ModelClientValidationRule( "cannotbered", FormatErrorMessage(MyClass.GetCustomMessage('somekey')); , instead it is showing the default Required field message as 'The message field is required'. Can you please help on this ?
@Rohit Remove the [Required] attribute from the Message property in my example. That's what's giving you the default required message. As far as pulling down a custom message, I would recommend this SO question. It should still be valid for ASP.NET Core.
@Rohit I think you've reached a point where asking a new question on SO would be beneficial. I'm having a little trouble following you in these last comments, and fresh question would open it up to more folks. All that being said, there is a CompareAttribute that I've used for password comparison in the past without issue.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.