ASP.Net Core MVC – Client-side validation for custom attribute

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?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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

Note:
There was a breaking change to the IClientModelValidator interface between RC1 and RC2. Both options are presented below – the rest of the code is the same between both versions.

Attribute (RC2 and beyond)

[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;
    }
}

Attribute (RC1)

[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 IEnumerable<ModelClientValidationRule> GetClientValidationRules(
        ClientModelValidationContext context)
    {
        yield return new ModelClientValidationRule(
            "cannotbered",
            FormatErrorMessage(ErrorMessage));
    }
}

Model

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

View

@model WebApplication22.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>
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x