web-dev-qa-db-fra.com

validation côté client dans l'attribut de validation personnalisé - asp.net mvc 4

J'ai suivi des articles et des tutoriels sur Internet afin de créer un attribut de validation personnalisé qui prend également en charge la validation côté client dans un site Web asp.net mvc 4. C'est ce que j'ai jusqu'à maintenant:

RequiredIfAttribute.cs

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] //Added
public class RequiredIfAttribute : ValidationAttribute, IClientValidatable
{
    private readonly string condition;
    private string propertyName; //Added

    public RequiredIfAttribute(string condition)
    {
        this.condition = condition;
        this.propertyName = propertyName; //Added
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        PropertyInfo propertyInfo = validationContext.ObjectType.GetProperty(this.propertyName); //Added
        Delegate conditionFunction = CreateExpression(validationContext.ObjectType, _condition);
        bool conditionMet = (bool)conditionFunction.DynamicInvoke(validationContext.ObjectInstance);

        if (conditionMet)
        {
            if (value == null)
            {
                return new ValidationResult(FormatErrorMessage(null));
            }
        }

        return ValidationResult.Success;
    }

    private Delegate CreateExpression(Type objectType, string expression)
    {
        LambdaExpression lambdaExpression = System.Linq.Dynamic.DynamicExpression.ParseLambda(objectType, typeof(bool), expression); //Added
        Delegate function = lambdaExpression.Compile();
        return function;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var modelClientValidationRule = new ModelClientValidationRule
        {
            ValidationType = "requiredif",
            ErrorMessage = ErrorMessage //Added
        };

        modelClientValidationRule.ValidationParameters.Add("param", this.propertyName); //Added
        return new List<ModelClientValidationRule> { modelClientValidationRule };
    }
}

Puis j'ai appliqué cet attribut dans une propriété d'une classe comme celle-ci

[RequiredIf("InAppPurchase == true", "InAppPurchase", ErrorMessage = "Please enter an in app purchase promotional price")] //Added "InAppPurchase"
public string InAppPurchasePromotionalPrice { get; set; }

public bool InAppPurchase { get; set; }

Donc, ce que je veux faire, c'est afficher un message d'erreur indiquant que le champ InAppPurchasePromotionalPrice est requis lorsque le champ InAppPurchase est vrai (cela signifie que coché sous la forme). Ce qui suit est le code pertinent de la vue:

<div class="control-group">
                <label class="control-label" for="InAppPurchase">Does your app include In App Purchase?</label>
                <div class="controls">
                    @Html.CheckBoxFor(o => o.InAppPurchase)
                    @Html.LabelFor(o => o.InAppPurchase, "Yes")
                </div>
            </div>
            <div class="control-group" id="InAppPurchasePromotionalPriceDiv" @(Model.InAppPurchase == true ? Html.Raw("style='display: block;'") : Html.Raw("style='display: none;'"))>
                <label class="control-label" for="InAppPurchasePromotionalPrice">App Friday Promotional Price for In App Purchase: </label>
                <div class="controls">
                    @Html.TextBoxFor(o => o.InAppPurchasePromotionalPrice, new { title = "This should be at the lowest price tier of free or $.99, just for your App Friday date." })
                    <span class="help-inline">
                        @Html.ValidationMessageFor(o => o.InAppPurchasePromotionalPrice)
                    </span>
                </div>
            </div>

Ce code fonctionne parfaitement, mais lorsque je soumets le formulaire, un message complet est demandé sur le serveur afin d’afficher le message. J'ai donc créé du code JavaScript pour activer la validation côté client:

requiredif.js

(function ($) {
    $.validator.addMethod('requiredif', function (value, element, params) {
        /*var inAppPurchase = $('#InAppPurchase').is(':checked');

        if (inAppPurchase) {
            return true;
        }

        return false;*/

        var isChecked = $(param).is(':checked');

        if (isChecked) {
            return false;
        }

        return true;
    }, '');

    $.validator.unobtrusive.adapters.add('requiredif', ['param'], function (options) {
        options.rules["requiredif"] = '#' + options.params.param;
        options.messages['requiredif'] = options.message;
    });
})(jQuery);

C'est la manière proposée dans MSDN et les tutoriels que j'ai trouvés

Bien sûr, j'ai également inséré les scripts nécessaires sous la forme:

  1. jquery.unobtrusive-ajax.min.js
  2. jquery.validate.min.js
  3. jquery.validate.unobtrusive.min.js
  4. requiredif.js

MAIS ... la validation côté client ne fonctionne toujours pas. Alors pourriez-vous s'il vous plaît m'aider à trouver ce qui me manque? Merci d'avance.

26

Jetez un oeil à ceci: http://thewayofcode.wordpress.com/tag/custom-unobtrusive-validation/

En utilisant ce tutoriel, mon code de validation personnalisé a fonctionné sans problème. La seule différence que je puisse distinguer dans votre code est la manière dont vous avez créé la fonction $.validator.unobtrusive.adapters.add. Les paramètres sont un peu différents, mais le problème est peut-être simplement que vous n'avez pas défini la partie rule de votre adaptateur.

Essayez d'utiliser quelque chose comme ça:

$.validator.unobtrusive.adapters.add("requiredif", ["requiredif"], function (options) {
    options.rules["requiredif"] = "#" + options.params.requiredif;
    options.messages["requiredif"] = options.message;
});

ou ca

$.validator.unobtrusive.adapters.add("requiredif", function (options) {
    options.rules["requiredif"] = "#" + options.element.name.replace('.', '_'); // mvc html helpers
    options.messages["requiredif"] = options.message;
});

À propos de la rule (tirée du lien):

Le tableau de règles jQuery pour cet élément HTML. L'adaptateur est attendu ajouter des éléments à ce tableau de règles pour le jQuery Validate validateurs qu'il veut attacher. Le nom est le nom de jQuery Validez la règle et la valeur correspond aux valeurs de paramètre pour jQuery Valider la règle.

34
Felipe Miosso

Il est à noter que l'attribut [RequiredIf] doit être ajouté au deuxième champ de formulaire dans le modèle de vue pour que la validation du client fonctionne.

0
Matthew Dresser