Esiste un modo attraverso le annotazioni dei dati per richiedere che una proprietà booleana sia impostata su true?
public class MyAwesomeObj{
public bool ThisMustBeTrue{get;set;}
}
Esiste un modo attraverso le annotazioni dei dati per richiedere che una proprietà booleana sia impostata su true?
public class MyAwesomeObj{
public bool ThisMustBeTrue{get;set;}
}
Risposte:
Puoi creare il tuo validatore:
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
}
return (bool) value == true;
questo è un confronto ridondante
Creerei un validatore sia per il lato server che per quello client. Utilizzando MVC e la convalida del modulo non invadente, ciò può essere ottenuto semplicemente effettuando le seguenti operazioni:
Innanzitutto, crea una classe nel tuo progetto per eseguire la convalida 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"
};
}
}
Successivamente, annota la proprietà appropriata nel tuo modello:
[EnforceTrue(ErrorMessage=@"Error Message")]
public bool ThisMustBeTrue{ get; set; }
Infine, abilita la convalida lato client aggiungendo il seguente script alla tua 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 GetClientValidationRules
che invia la nostra annotazione alla vista dal nostro modello.
Se si utilizzano file di risorse per fornire il messaggio di errore per l'internazionalizzazione, rimuovere la FormatErrorMessage
chiamata (o semplicemente chiamare la base) e modificare il GetClientValidationRules
metodo in questo modo:
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"
};
}
So che questo è un post precedente ma volevo condividere un semplice modo lato server per farlo. Si crea una proprietà pubblica impostata su true e si confronta il valore bool con quella proprietà. Se il tuo bool non è selezionato (per impostazione predefinita false) il modulo non verrà convalidato.
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 AgreeTerms { get; set; }
Codice del rasoio
@Html.CheckBoxFor(m => Model.AgreeTerms, new { id = "AgreeTerms", @checked = "checked" })
<label asp-for="AgreeTerms" class="control-label"></label>
<a target="_blank" href="/Terms">Read</a>
<br />
@Html.ValidationMessageFor(model => model.AgreeTerms, "", new { @class = "text-danger" })
@Html.HiddenFor(x => Model.isTrue)
Ho provato diverse soluzioni ma nessuna di esse ha funzionato completamente per me per ottenere la convalida sia lato client che lato server. Quindi cosa ho fatto nella mia applicazione MVC 5 per farlo funzionare:
Nel tuo ViewModel (per la convalida lato server):
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; }
Nella tua pagina Razor (per la convalida lato 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>
Vorrei solo indirizzare le persone al seguente Fiddle: https://dotnetfiddle.net/JbPh0X
L'utente ha aggiunto
[Range(typeof(bool), "true", "true", ErrorMessage = "You gotta tick the box!")]
alla sua proprietà booleana che fa funzionare la convalida lato server.
Per far funzionare anche la convalida lato client, hanno aggiunto il seguente script:
// 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);
}
}
Basta controllare per vedere se la sua rappresentazione di stringa è uguale a True
:
[RegularExpression("True")]
public bool TermsAndConditions { get; set; }
RegularExpressionAttribute
utilizza internamente Convert.ToString
per ottenere la rappresentazione di stringa del valore della proprietà (che viene consegnato ad esso come un object
).
Puoi creare il tuo attributo o utilizzare CustomValidationAttribute .
Ecco come useresti CustomValidationAttribute:
[CustomValidation(typeof(BoolValidation), "ValidateBool")]
dove BoolValidation è definito come:
public class BoolValidation
{
public static ValidationResult ValidateBool(bool boolToBeTrue)
{
if (boolToBeTrue)
{
return ValidationResult.Success;
}
else
{
return new ValidationResult(
"Bool must be true.");
}
}
[Required]
attributo sta per richiedere qualsiasi valore - può essere vero o falso. Dovresti usare un'altra convalida per quello.
Per ASP.NET Core MVC, ecco la convalida di client e server, basata sulla soluzione di 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);
}
}
E poi sul client:
$.validator.addMethod("enforcetrue", function (value, element, param) {
return element.checked;
});
$.validator.unobtrusive.adapters.addBool("enforcetrue");
Quindi l'utilizzo è:
[EnforceTrue(ErrorMessage = "Please tick the checkbox")]
public bool IsAccepted { get; set; }
required
attributo nell'input HTML, come:<input asp-for="..." class="..." id="..." type="checkbox" required/>
Seguendo il post di ta.speot.is e il commento di Jerad Rose:
Il post fornito non funzionerà sul lato client con una convalida discreta. Questo dovrebbe funzionare in entrambi i campi (client e server):
[RegularExpression("(True|true)")]
public bool TermsAndConditions { get; set; }
regex
metodo discreto che definisce prima controlla se la casella di controllo è opzionale prima di convalidare la regex, il che ha senso, tranne che jquery.validate sembra considerare facoltativa qualsiasi casella di controllo non selezionata. tl; dr Esegue la regex solo sulle caselle di controllo selezionate. Possiamo aggiungere uno shim per il regex
validator
metodo o semplicemente creare un validatore personalizzato.
.NET Core MVC: casella di controllo obbligatoria con annotazioni dei dati
public class MyModel
{
[Display(Name = "Confirmation")]
[Range(typeof(bool), "true", "true", ErrorMessage = "Please check the Confirmation checkbox.")]
public bool IsConfirmed { get; set; }
}
<div class="custom-control custom-checkbox col-10">
<input type="checkbox" asp-for="IsConfirmed" class="custom-control-input" />
<label class="custom-control-label" for="IsConfirmed">
"By clicking 'submit', I confirm."
</label>
<span asp-validation-for="IsConfirmed" class="text-danger"></span>
</div>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
<script type="text/javascript">
$(document).ready(function () {
// extend range validator method to treat checkboxes differently
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);
}
}
});
</script>
Non conosco un modo per utilizzare DataAnnotations, ma questo è facilmente realizzabile nel tuo controller.
public ActionResult Add(Domain.Something model)
{
if (!model.MyCheckBox)
ModelState.AddModelError("MyCheckBox", "You forgot to click accept");
if (ModelState.IsValid) {
//'# do your stuff
}
}
L'unica altra opzione sarebbe costruire un validatore personalizzato per il lato server e un validatore remoto per il lato client (la convalida remota è disponibile solo in MVC3 +)
Hai gli elementi appropriati impostati nel web.config ?
Ciò potrebbe causare il mancato funzionamento della convalida.
Puoi anche provare a creare un attributo di convalida personalizzato (poiché [Required]
si preoccupa solo se esiste o meno e ti interessa il valore):
[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);
}
}
Quindi, utilizzo:
[RequiredTrue(ErrorMessage="{0} requires acceptance to continue.")]
public bool Agreement {get; set;}
Da qui .
Questo è ciò che ha funzionato per me. Nient'altro ha fatto. Mvc 5:
Modello
public string True
{
get
{
return "true";
}
}
[Required]
[Compare("True", ErrorMessage = "Please agree to the Acknowlegement")]
public bool Acknowlegement { get; set; }
Visualizza
@Html.HiddenFor(m => m.True)
@Html.EditorFor(model => model.Acknowlegement, new { htmlAttributes = Model.Attributes })
@Html.ValidationMessageFor(model => model.Acknowlegement, "", new { @class = "text-danger" })
Ho provato a usare la risposta di fields.cage e non ha funzionato per me, ma qualcosa di più semplice ha funzionato, e non sono sicuro esattamente perché (versione diversa di Razor, forse?), Ma tutto quello che dovevo fare era questo:
[Required]
[Range(typeof(bool), "true", "true", ErrorMessage = "Agreement required.")]
[Display(Name = "By clicking here, I agree that my firstborn child will etc etc...")]
public bool Agreement1Checked { get; set; }
E nel file .cshtml:
@Html.CheckBoxFor(m => m.Agreement1Checked)
@Html.LabelFor(m => m.Agreement1Checked)
@Html.ValidationMessageFor(m => m.Agreement1Checked)
[NaN, NaN]
dove dovrebbe essere[true, true]
Penso che il modo migliore per gestirlo sia semplicemente controllare nel tuo controller se la casella è vera, altrimenti aggiungi semplicemente un errore al tuo modello e visualizza di nuovo la tua vista.
Come affermato in precedenza, tutto ciò che [Obbligatorio] fa è assicurarsi che ci sia un valore e nel tuo caso, se non selezionato, ottieni comunque false.
/// <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 } };
}
}