web-dev-qa-db-fra.com

Le modèle MVC nécessite vrai

Existe-t-il un moyen par le biais d'annotations de données d'exiger qu'une propriété booléenne soit définie sur true?

public class MyAwesomeObj{
    public bool ThisMustBeTrue{get;set;}
}
74
Marty Trenouth

Vous pouvez créer votre propre validateur:

public class IsTrueAttribute : ValidationAttribute
{
    #region Overrides of ValidationAttribute

    /// <summary>
    /// Determines whether the specified value of the object is valid. 
    /// </summary>
    /// <returns>
    /// true if the specified value is valid; otherwise, false. 
    /// </returns>
    /// <param name="value">The value of the specified validation object on which the <see cref="T:System.ComponentModel.DataAnnotations.ValidationAttribute"/> is declared.
    ///                 </param>
    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;
    }

    #endregion
}
47
HackedByChinese

Je créerais un validateur à la fois côté serveur ET côté client. En utilisant MVC et une validation de formulaire discrète, cela peut être réalisé simplement en procédant comme suit:

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

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

Ensuite, annotez la propriété appropriée dans votre modèle:

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

Enfin, activez la validation côté client en ajoutant le script suivant à votre vue:

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

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

Si vous utilisez des fichiers de ressources pour fournir le message d'erreur pour l'internationalisation, supprimez l'appel FormatErrorMessage (ou appelez simplement la base) et ajustez la méthode GetClientValidationRules comme ceci:

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
    string errorMessage = String.Empty;
    if(String.IsNullOrWhiteSpace(ErrorMessage))
    {
        // Check if they supplied an error message resource
        if(ErrorMessageResourceType != null && !String.IsNullOrWhiteSpace(ErrorMessageResourceName))
        {
            var resMan = new ResourceManager(ErrorMessageResourceType.FullName, ErrorMessageResourceType.Assembly);
            errorMessage = resMan.GetString(ErrorMessageResourceName);
        }
    }
    else
    {
        errorMessage = ErrorMessage;
    }

    yield return new ModelClientValidationRule
    {
        ErrorMessage = errorMessage,
        ValidationType = "enforcetrue"
    };
}
127
dazbradbury

Je sais que c'est un article plus ancien mais je voulais partager un moyen simple côté serveur de le faire. Vous créez une propriété publique définie sur true et comparez votre valeur booléenne à cette propriété. Si votre bool n'est pas coché (par défaut false) le formulaire ne sera pas validé.

public bool isTrue
{ get { return true; } }

[Required]
[Display(Name = "I agree to the terms and conditions")]
[Compare("isTrue", ErrorMessage = "Please agree to Terms and Conditions")]
public bool iAgree { get; set; }
80
fields.cage

J'ai essayé plusieurs solutions, mais aucune d'entre elles n'a fonctionné complètement pour moi pour obtenir la validation côté client et côté serveur. Donc, ce que j'ai fait dans mon application MVC 5 pour le faire fonctionner:

Dans votre ViewModel (pour la validation côté serveur):

public bool IsTrue => true;

[Required]
[Display(Name = "I agree to the terms and conditions")]
[Compare(nameof(IsTrue), ErrorMessage = "Please agree to Terms and Conditions")]
public bool HasAcceptedTermsAndConditions { get; set; }

Dans votre page Razor (pour la validation côté client):

<div class="form-group">
   @Html.CheckBoxFor(m => m.HasAcceptedTermsAndConditions)
   @Html.LabelFor(m => m.HasAcceptedTermsAndConditions)
   @Html.ValidationMessageFor(m => m.HasAcceptedTermsAndConditions)

   @Html.Hidden(nameof(Model.IsTrue), "true")
</div>
11
Kapé

Je voudrais simplement diriger les gens vers le violon suivant: https://dotnetfiddle.net/JbPh0X

L'utilisateur a ajouté [Range(typeof(bool), "true", "true", ErrorMessage = "You gotta tick the box!")] à sa propriété booléenne, ce qui fait fonctionner la validation côté serveur.

Afin que la validation côté client fonctionne également, ils ont ajouté le script suivant:

// extend jquery range validator to work for required checkboxes
var defaultRangeValidator = $.validator.methods.range;
$.validator.methods.range = function(value, element, param) {
    if(element.type === 'checkbox') {
        // if it's a checkbox return true if it is checked
        return element.checked;
    } else {
        // otherwise run the default validation function
        return defaultRangeValidator.call(this, value, element, param);
    }
}
8
Harvey

Vérifiez simplement si sa représentation sous forme de chaîne est égale à True:

[RegularExpression("True")]
public bool TermsAndConditions { get; set; }
6
ta.speot.is

Vous pouvez soit créer votre propre attribut, soit utiliser le CustomValidationAttribute .

Voici comment vous utiliseriez le CustomValidationAttribute:

[CustomValidation(typeof(BoolValidation), "ValidateBool")]

où BoolValidation est défini comme:

public class BoolValidation
{
  public static ValidationResult ValidateBool(bool boolToBeTrue)
  {
    if (boolToBeTrue)
    {
      return ValidationResult.Success;
    }
    else
    {
      return new ValidationResult(
          "Bool must be true.");
    }
  }
5
Matthew Manela

[Required] l'attribut signifie exiger tout valeur - il peut être vrai ou faux. Vous devez utiliser une autre validation pour cela.

5
Sergey Kudriavtsev

Pour ASP.NET Core MVC voici la validation client et serveur, basée sur la solution de dazbradbury

public class EnforceTrueAttribute : ValidationAttribute, IClientModelValidator
{
    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;
    }

    public void AddValidation(ClientModelValidationContext context)
    {
        MergeAttribute(context.Attributes, "data-val", "true");
        var errorMessage = ErrorMessage ?? 
            $"The value for field {context.ModelMetadata.GetDisplayName()} must be true.";
        MergeAttribute(context.Attributes, "data-val-enforcetrue", errorMessage);
    }

    private void MergeAttribute(IDictionary<string, string> attributes,
        string key,
        string value)
    {
        if (attributes.ContainsKey(key))
        {
            return;
        }
        attributes.Add(key, value);
    }
}

Et puis sur le client:

$.validator.addMethod("enforcetrue", function (value, element, param) {
    return element.checked;
});

$.validator.unobtrusive.adapters.addBool("enforcetrue");

L'utilisation est alors:

[EnforceTrue(ErrorMessage = "Please tick the checkbox")]
public bool IsAccepted { get; set; }
2
Matt

Avez-vous les éléments appropriés configurés dans le web.config ?

Cela pourrait empêcher la validation de fonctionner.

Vous pouvez également essayer de créer un attribut de validation personnalisé (puisque [Required] ne se soucie que s'il existe ou non, et vous vous souciez de la valeur):

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
sealed public class RequiredTrueAttribute : ValidationAttribute
{
    // Internal field to hold the mask value.
    readonly bool accepted;

    public bool Accepted
    {
        get { return accepted; }
    }

    public RequiredTrueAttribute(bool accepted)
    {
        this.accepted = accepted;
    }

    public override bool IsValid(object value)
    {
        bool isAccepted = (bool)value;
        return (isAccepted == true);
    }

    public override string FormatErrorMessage(string name)
    {
        return String.Format(CultureInfo.CurrentCulture,
          ErrorMessageString, name, this.Accepted);
    }
}

Ensuite, utilisation:

[RequiredTrue(ErrorMessage="{0} requires acceptance to continue.")]
public bool Agreement {get; set;}

De ici .

2
George Stocker

Suivi du message de ta.speot.is et du commentaire de Jerad Rose:

Le message donné ne fonctionnera pas côté client avec une validation discrète. Cela devrait fonctionner dans les deux camps (client et serveur):

[RegularExpression("(True|true)")]
public bool TermsAndConditions { get; set; }
2
lobotommy

C'est ce qui a fonctionné pour moi. Rien d'autre ne l'a fait. Mvc 5:

Modèle

public string True
{
  get
  {
    return "true";
  }
}

[Required]
[Compare("True", ErrorMessage = "Please agree to the Acknowlegement")]
public bool Acknowlegement { get; set; }

Voir

  @Html.HiddenFor(m => m.True)
  @Html.EditorFor(model => model.Acknowlegement, new { htmlAttributes = Model.Attributes })
  @Html.ValidationMessageFor(model => model.Acknowlegement, "", new { @class = "text-danger" })

enter image description here

enter image description here

1
toddmo

Je ne connais pas de chemin à travers DataAnnotations, mais cela se fait facilement dans votre contrôleur.

public ActionResult Add(Domain.Something model)
{

    if (!model.MyCheckBox)
        ModelState.AddModelError("MyCheckBox", "You forgot to click accept");

    if (ModelState.IsValid) {
        //'# do your stuff
    }

}

La seule autre option serait de construire un validateur personnalisé pour le côté serveur et un validateur distant pour le côté client (la validation à distance n'est disponible que dans MVC3 +)

1
Chase Florell
/// <summary> 
///  Summary : -CheckBox for or input type check required validation is not working the root cause and solution as follows
///
///  Problem :
///  The key to this problem lies in interpretation of jQuery validation 'required' rule. I digged a little and find a specific code inside a jquery.validate.unobtrusive.js file:
///  adapters.add("required", function (options) {
///  if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
///    setValidationValues(options, "required", true);
///    }
///   });
///   
///  Fix: (Jquery script fix at page level added in to check box required area)
///  jQuery.validator.unobtrusive.adapters.add("brequired", function (options) {
///   if (options.element.tagName.toUpperCase() == "INPUT" && options.element.type.toUpperCase() == "CHECKBOX") {
///              options.rules["required"] = true;
///   if (options.message) {
///                   options.messages["required"] = options.message;
///                       }
///  Fix : (C# Code for MVC validation)
///  You can see it inherits from common RequiredAttribute. Moreover it implements IClientValidateable. This is to make assure that rule will be propagated to client side (jQuery validation) as well.
///  
///  Annotation example :
///   [BooleanRequired]
///   public bool iAgree { get; set' }
/// </summary>


public class BooleanRequired : RequiredAttribute, IClientValidatable
{

    public BooleanRequired()
    {
    }

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

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        return new ModelClientValidationRule[] { new ModelClientValidationRule() { ValidationType = "brequired", ErrorMessage = this.ErrorMessage } };
    }
}
0

Découvrez la validation infaillible ici . Vous pouvez le télécharger/l'installer via Nuget.

C'est une super petite bibliothèque pour ce genre de chose.

0
DavidWainwright

Je pense que la meilleure façon de gérer cela est simplement de vérifier dans votre contrôleur si la case est vraie, sinon ajoutez simplement une erreur à votre modèle et faites-le réafficher votre vue.

Comme indiqué précédemment, tout [Obligatoire] fait est de s'assurer qu'il y a une valeur et dans votre cas, si elle n'est pas cochée, vous obtenez toujours faux.

0
samack