m.edmondson
m.edmondson

Reputation: 30922

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?

Upvotes: 45

Views: 31997

Answers (1)

Will Ray
Will Ray

Reputation: 10889

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

Upvotes: 65

Related Questions