Comment manipuler booléens / cases à cocher ASP.NET MVC 2 avec des annotations de données?

j'ai un modèle de vue comme celui-ci:

public class SignUpViewModel
{
    [Required(ErrorMessage = "Bitte lesen und akzeptieren Sie die AGB.")]
    [DisplayName("Ich habe die AGB gelesen und akzeptiere diese.")]
    public bool AgreesWithTerms { get; set; }
}

afficher le code de balisage:

<%= Html.CheckBoxFor(m => m.AgreesWithTerms) %>
<%= Html.LabelFor(m => m.AgreesWithTerms)%>

le résultat:

aucune validation n'est exécutée. C'est bon pour l'instant parce que bool est un type de valeur et jamais null. Mais même si je rends les accords nulles, cela ne marchera pas car le compilateur crie

Modèles "peut être utilisé uniquement avec accès sur le terrain, l'accès à la propriété, à une seule dimension du tableau d'index, ou expressions indexeuses personnalisées à un seul paramètre."

alors, quelle est la bonne façon de gérer ça?

46
demandé sur asp_net 2010-02-11 17:47:15

12 réponses

ma Solution est la suivante (ce n'est pas très différent des réponses déjà soumises, mais je crois que c'est mieux nommé):

/// <summary>
/// Validation attribute that demands that a boolean value must be true.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class MustBeTrueAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        return value != null && value is bool && (bool)value;
    }
}

, Alors vous pouvez l'utiliser comme ceci dans votre modèle:

[MustBeTrue(ErrorMessage = "You must accept the terms and conditions")]
[DisplayName("Accept terms and conditions")]
public bool AcceptsTerms { get; set; }
91
répondu s1mm0t 2010-04-25 23:31:46

je créerais un validateur pour le côté serveur et le côté Client. En utilisant MVC et la validation discrète du formulaire, ceci peut être réalisé simplement en faisant ce qui suit:

tout d'abord, créez une classe dans votre projet pour effectuer la validation côté serveur comme suit:

public class EnforceTrueAttribute : ValidationAttribute, IClientValidatable
{
    public override bool IsValid(object value)
    {
        if (value == null) return false;
        if (value.GetType() != typeof(bool)) throw new InvalidOperationException("can only be used on boolean properties.");
        return (bool)value == true;
    }

    public override string FormatErrorMessage(string name)
    {
        return "The " + name + " field must be checked in order to continue.";
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRule
        {
            ErrorMessage = String.IsNullOrEmpty(ErrorMessage) ? FormatErrorMessage(metadata.DisplayName) : ErrorMessage,
            ValidationType = "enforcetrue"
        };
    }
}

à la suite de cela, annoter la propriété appropriée dans votre modèle:

[EnforceTrue(ErrorMessage=@"Error Message")]
public bool ThisMustBeTrue{ get; set; }

et enfin, activez la validation côté client en ajoutant ce qui suit: script à votre vue:

<script type="text/javascript">
    jQuery.validator.addMethod("enforcetrue", function (value, element, param) {
        return element.checked;
    });
    jQuery.validator.unobtrusive.adapters.addBool("enforcetrue");
</script>

Note: Nous avons déjà créé une méthode GetClientValidationRules qui pousse notre annotation à la vue de notre modèle.

48
répondu dazbradbury 2012-01-27 17:56:55

Je l'ai obtenu en créant un attribut personnalisé:

public class BooleanRequiredAttribute : RequiredAttribute 
{
    public override bool IsValid(object value)
    {
        return value != null && (bool) value;
    }
}
18
répondu asp_net 2010-02-11 15:17:14
[Compare("Remember", ErrorMessage = "You must accept the terms and conditions")]
public bool Remember { get; set; }
6
répondu Vedat Taylan 2017-01-20 08:03:26

c'est peut-être un "hack" mais vous pouvez utiliser l'attribut de portée intégré:

[Display(Name = "Accepted Terms Of Service")]
[Range(typeof(bool), "true", "true")]
public bool Terms { get; set; }

le seul problème est la chaîne de caractères" warning "qui dit"The FIELDNAME must be between True and true".

5
répondu ProVega 2013-06-03 22:02:28

"Nécessaire" est la bonne validation, ici. Vous voulez quelque chose de semblable à "Doit avoir la valeur true," qui n'est pas le même que "Nécessaire". Que diriez-vous d'utiliser quelque chose comme:

[RegularExpression("^true")]

?

4
répondu Craig Stuntz 2010-02-11 15:06:25

ma solution est cet attribut personnalisé simple pour les valeurs booléennes:

public class BooleanAttribute : ValidationAttribute
{
    public bool Value
    {
        get;
        set;
    }

    public override bool IsValid(object value)
    {
        return value != null && value is bool && (bool)value == Value;
    }
}

, Alors vous pouvez l'utiliser comme ceci dans votre modèle:

[Required]
[Boolean(Value = true, ErrorMessage = "You must accept the terms and conditions")]
[DisplayName("Accept terms and conditions")]
public bool AcceptsTerms { get; set; }
3
répondu Maksymilian Majer 2010-04-06 17:54:41

Je ne fais que prendre le meilleur des solutions existantes et le rassembler en une seule réponse qui permet à la fois la validation côté serveur et côté client.

la valeur à appliquer aux propriétés du modèle a pour garantir une valeur de bool doit être vraie:

/// <summary>
/// Validation attribute that demands that a <see cref="bool"/> value must be true.
/// </summary>
/// <remarks>Thank you <c>http://stackoverflow.com/a/22511718</c></remarks>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class MustBeTrueAttribute : ValidationAttribute, IClientValidatable
{
    /// <summary>
    /// Initializes a new instance of the <see cref="MustBeTrueAttribute" /> class.
    /// </summary>
    public MustBeTrueAttribute()
        : base(() => "The field {0} must be checked.")
    {
    }

    /// <summary>
    /// Checks to see if the given object in <paramref name="value"/> is <c>true</c>.
    /// </summary>
    /// <param name="value">The value to check.</param>
    /// <returns><c>true</c> if the object is a <see cref="bool"/> and <c>true</c>; otherwise <c>false</c>.</returns>
    public override bool IsValid(object value)
    {
        return (value as bool?).GetValueOrDefault();
    }

    /// <summary>
    /// Returns client validation rules for <see cref="bool"/> values that must be true.
    /// </summary>
    /// <param name="metadata">The model metadata.</param>
    /// <param name="context">The controller context.</param>
    /// <returns>The client validation rules for this validator.</returns>
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        if (metadata == null)
            throw new ArgumentNullException("metadata");
        if (context == null)
            throw new ArgumentNullException("context");

        yield return new ModelClientValidationRule
            {
                ErrorMessage = FormatErrorMessage(metadata.DisplayName),
                ValidationType = "mustbetrue",
            };
    }
}

le JavaScript à inclure pour faire usage de validation discrète.

jQuery.validator.addMethod("mustbetrue", function (value, element) {
    return element.checked;
});
jQuery.validator.unobtrusive.adapters.addBool("mustbetrue");
3
répondu James Skimming 2014-03-20 14:56:53

pour les personnes qui ont de la difficulté à obtenir ce travail de validation du côté du client (anciennement moi): assurez-vous que vous avez aussi

  1. Inclus <% Html.Validation valide (); % > avant le formulaire dans la vue
  2. Utilisé <%= Html.ValidationMessage ou Html.ValidationMessageFor pour le champ
  3. a créé un DataAnnotationsModelValidator qui renvoie une règle avec un type de validation personnalisé
  4. a enregistré la classe dérivant de DataAnnotationsModelValidator dans le Global.Application_Start

http://www.highoncoding.com/Articles/729_Creating_Custom_Client_Side_Validation_in_ASP_NET_MVC_2_0.aspx

est un bon tutoriel sur ce sujet, mais manque l'étape 4.

2
répondu Craig Lebowitz 2011-04-28 17:17:37

la bonne façon de faire ceci est de vérifier le type!

[Range(typeof(bool), "true", "true", ErrorMessage = "You must or else!")]
public bool AgreesWithTerms { get; set; }
2
répondu saj 2016-01-18 20:28:03

a trouvé une solution plus complète ici (validation côté serveur et côté client):

http://blog.degree.no/2012/03/validation-of-required-checkbox-in-asp-net-mvc/#comments

1
répondu user1608132 2012-10-10 18:59:39

il suffit d'ajouter [RegularExpression]:

[DisplayName("I accept terms and conditions")]
[RegularExpression("True", ErrorMessage = "You must accept the terms and conditions")]
public bool AgreesWithTerms { get; set; }

Note - "vrai" doit commencer par le capital t

1
répondu mvt 2015-05-07 11:57:37