Domanda

Ho un modello di visualizzazione come questo:

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

Il codice di markup della vista:

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

Il risultato:

Non viene eseguita alcuna convalida.Per il momento va bene perché bool è un tipo di valore e mai nullo.Ma anche se rendo nullable AgreesWithTerms, non funzionerà perché il compilatore grida

"I modelli possono essere utilizzati solo con accesso al campo, accesso alla proprietà, indice di matrice a dimensione singola o espressioni dell'indicizzatore personalizzato a parametro singolo."

Quindi, qual è il modo corretto di gestire questa situazione?

È stato utile?

Soluzione 3

ho ottenuto con la creazione di un attributo personalizzato:

public class BooleanRequiredAttribute : RequiredAttribute 
{
    public override bool IsValid(object value)
    {
        return value != null && (bool) value;
    }
}

Altri suggerimenti

La mia soluzione è la seguente (non è molto diverso per le risposte già presentate, ma credo che prende il nome migliore):

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

Quindi è possibile utilizzarlo come questo nel tuo modello:

[MustBeTrue(ErrorMessage = "You must accept the terms and conditions")]
[DisplayName("Accept terms and conditions")]
public bool AcceptsTerms { get; set; }

Vorrei creare un validatore per server e lato client. Utilizzando MVC e validazione dei form discreto, ciò può essere ottenuto semplicemente facendo quanto segue:

In primo luogo, creare una classe nel progetto per eseguire la validazione lato server in questo modo:

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

A seguito di questo, annotare la proprietà appropriata nel modello:

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

E, infine, consentire la validazione lato client aggiungendo il seguente script alla vostra vista:

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

Nota:. Abbiamo già creato un metodo di GetClientValidationRules che spinge la nostra annotazione la vista dal nostro modello

[Compare("Remember", ErrorMessage = "You must accept the terms and conditions")]
public bool Remember { get; set; }

Questo potrebbe essere un "hack", ma è possibile utilizzare il costruito nel dell'attributo Intervallo:

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

L'unico problema è il "avvertimento" stringa dirà "La FIELDNAME deve essere compreso tra Vero e proprio".

"Richiesto" è la validazione sbagliato, qui. Volete qualcosa di simile a "deve avere il valore vero", che non è lo stesso di "Required". Cosa succede ad usare qualcosa di simile a:

[RegularExpression("^true")]

La mia soluzione è questo semplice attributo personalizzato per i valori booleani:

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

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

Quindi è possibile utilizzarlo come questo nel tuo modello:

[Required]
[Boolean(Value = true, ErrorMessage = "You must accept the terms and conditions")]
[DisplayName("Accept terms and conditions")]
public bool AcceptsTerms { get; set; }

Sto solo prendendo il meglio delle soluzioni esistenti e la messa insieme in una singola risposta che consente sia la validazione lato server e lato client.

Il applicano a modellare una proprietà al fine di garantire un valore booleano deve essere vero:

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

La Javascript per includere a fare uso di convalida discreto.

jQuery.validator.addMethod("mustbetrue", function (value, element) {
    return element.checked;
});
jQuery.validator.unobtrusive.adapters.addBool("mustbetrue");

Per le persone che hanno difficoltà a far funzionare questo per la convalida sul lato client (in precedenza io):assicurati di averlo anche tu

  1. Incluso <% Html.EnableClientValidation();%> prima del modulo nella vista
  2. Utilizzato <%= Html.ValidationMessage o Html.ValidationMessageFor per il campo
  3. Creato un DataAnnotationsModelValidator che restituisce una regola con un tipo di convalida personalizzato
  4. Registrata la classe derivante da DataAnnotationsModelValidator nella Global.Application_Start

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

è un buon tutorial su come farlo, ma salta il passaggio 4.

Il modo corretto per farlo è quello di verificare il tipo!

[Range(typeof(bool), "true", "true", ErrorMessage = "You must or else!")]
public bool AgreesWithTerms { get; set; }

Trovato una soluzione più completa qui (server e la validazione lato client):

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

E 'sufficiente aggiungere [espressione regolare]:

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

Nota - "True" deve iniziare con capitale T

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top