web-dev-qa-db-fra.com

ASP.Net Core MVC - Validation côté client pour l'attribut personnalisé

Dans les versions précédentes du framework MVC, la validation personnalisée était obtenue en implémentant IClientValidatable et la méthode GetClientValidationRules.

Cependant dans ASP.Net Core MVC nous n'avons pas cette interface , bien que nous ayons IClientModelValidator qui définit une méthode très similaire. La mise en œuvre de ce qui n'est jamais appelé cependant.

Alors - comment implémenter la validation côté client pour un attribut personnalisé dans ASP.NET Core MVC?

24
m.edmondson

IClientModelValidator est en fait la bonne interface. J'ai fait un exemple d'implémentation artificielle ci-dessous.

Remarque: Il y avait un rupture de changement à l'interface IClientModelValidator entre RC1 et RC2. Les deux options sont présentées ci-dessous - le reste du code est le même entre les deux versions.

Attribut (RC2 et au-delà)

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

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

Modèle

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

Vue

@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>
}
43
Will Ray