132 votes

Validation ASP.NET MVC conditionnelle

Comment utiliser les annotations de données pour faire une condition de validation sur le modèle?

Par exemple, disons que nous avons le modèle suivant (Personne et Senior):

public class Person
{
    [Required(ErrorMessage = "*")]
    public string Name
    {
        get;
        set;
    }

    public bool IsSenior
    {
        get;
        set;
    }

    public Senior Senior
    {
        get;
        set;
    }
}

public class Senior
{
    [Required(ErrorMessage = "*")]//this should be conditional validation, based on the "IsSenior" value
    public string Description
    {
        get;
        set;
    }
}

Et le point de vue suivant:

<%= Html.EditorFor(m => m.Name)%>
<%= Html.ValidationMessageFor(m => m.Name)%>

<%= Html.CheckBoxFor(m => m.IsSenior)%>
<%= Html.ValidationMessageFor(m => m.IsSenior)%>

<%= Html.CheckBoxFor(m => m.Senior.Description)%>
<%= Html.ValidationMessageFor(m => m.Senior.Description)%>

Je voudrais être le "Principal.Description de la propriété" conditionnel champ obligatoire basé sur la sélection de la "IsSenior" propery (true -> obligatoire). Comment mettre en œuvre conditionnelle de validation ASP.NET MVC 2 avec annotations de données?


Mise à JOUR

Trouvé de solution sympa. Regardez ci-dessous.

157voto

viperguynaz Points 4702

Il y a une bien meilleure façon d’ajouter des règles de validation conditionnelle dans MVC3. Avoir votre modèle hérite de IValidatableObject et implémente la méthode Validate :

Voir plus d’une description à http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx

70voto

Peter Stegnar Points 3819

J'ai résolu avec la manipulation de la "ModelState" dictionnaire qui est contenue par le contrôleur. ModelState dictionnaire inclure tous les membres doivent être validés.

Voici la solution:

Si vous avez besoin de mettre en œuvre un conditionnel de validation basée sur un certain domaine (par exemple, si A=vrai, alors B est requise), tout en conservant la propriété message d'erreur de niveau (ce n'est pas vrai pour les validateurs personnalisés qui sont sur le niveau de l'objet), vous pouvez l'obtenir par la manipulation "ModelState simplement d'enlever les validations.

...D'une certaine classe...

public bool PropertyThatRequiredAnotherFieldToBeFilled
{
  get;
  set;
}

[Required(ErrorMessage = "*")] 
public string DepentedProperty
{
  get;
  set;
}

...classe continue...

...Dans certains contrôleur de l'action ...

if (!PropertyThatRequiredAnotherFieldToBeFilled)
{
   this.ModelState.Remove("DepentedProperty");
}

...

Par cela, nous obtenons conditionnelle de validation, tout en laissant tout de même.


Mise à JOUR:

Mon final de mise en œuvre de regarder comme ça que j'ai mis en oeuvre avec une interface de modèle et de l'action de l'attribut qui permet de valider le modèle qui implémente l'interface mentionnées. Interface prescrit le Valider(ModelStateDictionary modelState) de la méthode. Attribut sur l'action, il suffit d'appeler le Valider(modelState) sur IValidatiorSomething.

Je ne voulais pas compliquer cette réponse, que je n'ai pas parler de la finale de détails de mise en œuvre, à la fin de la production questions de code.

42voto

Dan Hunex Points 1807

J'ai eu le même problème hier, mais je l'ai fait dans un très propre manière qui fonctionne pour à la fois côté client et côté serveur de validation.

Condition: Basé sur la valeur de la propriété dans le modèle, vous voulez faire une autre propriété requise. Voici le code

public class RequiredIfAttribute : RequiredAttribute
{
    private String PropertyName { get; set; }
    private Object DesiredValue { get; set; }

    public RequiredIfAttribute(String propertyName, Object desiredvalue)
    {
        PropertyName = propertyName;
        DesiredValue = desiredvalue;
    }

    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        Object instance = context.ObjectInstance;
        Type type = instance.GetType();
        Object proprtyvalue = type.GetProperty(PropertyName).GetValue(instance, null);
        if (proprtyvalue.ToString() == DesiredValue.ToString())
        {
            ValidationResult result = base.IsValid(value, context);
            return result;
        }
        return ValidationResult.Success;
    }
}

Ici PropertyName est la propriété sur laquelle vous voulez faire de votre condition DesiredValue est la valeur de la PropertyName (propriété) pour lesquels d'autres biens doit être validé pour l'

Dire que vous avez l'suivantes

public class User
{
    public UserType UserType { get; set; }

    [RequiredIf("UserType", UserType.Admin, ErrorMessageResourceName = "PasswordRequired", ErrorMessageResourceType = typeof(ResourceString))]
    public string Password
    {
        get;
        set;
    }
}

Au dernier mais non le moins , inscrivez-adaptateur pour votre attribut de sorte qu'il peut faire à la validation côté client (je l'ai mis dans le mondial.asax, Application_Start)

 DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredIfAttribute),typeof(RequiredAttributeAdapter));

18voto

Pavel Chuchuva Points 12220

Vous pouvez désactiver les validateurs conditionnellement en supprimant les erreurs de ModelState :

8voto

Simon Ince Points 141

Merci Merritt  :)

J’ai juste mis à jour ce MVC 3 dans le cas où tout le monde estime qu’il est utile ; http://blogs.msdn.com/b/simonince/archive/2011/02/04/Conditional-validation-in-ASP-NET-MVC-3.aspx

Simon

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X