Existe uma maneira de as anotações de dados exigirem que uma propriedade booleana seja definida como true?
public class MyAwesomeObj{
public bool ThisMustBeTrue{get;set;}
}
asp.net-mvc
data-annotations
Marty Trenouth
fonte
fonte
Respostas:
Você pode criar seu próprio validador:
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 }
fonte
return (bool) value == true;
esta é uma comparação redundanteGostaria de criar um validador para o lado do servidor E do cliente. Usando MVC e validação de formulário discreto, isso pode ser alcançado simplesmente fazendo o seguinte:
Em primeiro lugar, crie uma classe em seu projeto para realizar a validação do lado do servidor assim:
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" }; } }
Em seguida, anote a propriedade apropriada em seu modelo:
[EnforceTrue(ErrorMessage=@"Error Message")] public bool ThisMustBeTrue{ get; set; }
E, finalmente, habilite a validação do lado do cliente adicionando o seguinte script à sua Visualização:
<script type="text/javascript"> jQuery.validator.addMethod("enforcetrue", function (value, element, param) { return element.checked; }); jQuery.validator.unobtrusive.adapters.addBool("enforcetrue"); </script>
Nota: Já criamos um método
GetClientValidationRules
que empurra nossa anotação para a vista de nosso modelo.Se estiver usando arquivos de recursos para fornecer a mensagem de erro para internacionalização, remova a
FormatErrorMessage
chamada (ou apenas chame a base) e ajuste oGetClientValidationRules
método da seguinte maneira: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" }; }
fonte
Eu sei que este é um post mais antigo, mas gostaria de compartilhar uma maneira simples do lado do servidor para fazer isso. Você cria uma propriedade pública definida como true e compara seu bool com essa propriedade. Se o seu bool não estiver marcado (por padrão, falso), o formulário não será validado.
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; }
Código de navalha
@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)
fonte
Tentei várias soluções, mas nenhuma delas funcionou completamente para eu conseguir a validação do lado do cliente e do servidor. Então, o que fiz em meu aplicativo MVC 5 para fazê-lo funcionar:
Em seu ViewModel (para validação do lado do servidor):
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; }
Em sua página do Razor (para validação do lado do cliente):
<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>
fonte
Eu gostaria apenas de direcionar as pessoas para o seguinte Fiddle: https://dotnetfiddle.net/JbPh0X
O usuário adicionou
[Range(typeof(bool), "true", "true", ErrorMessage = "You gotta tick the box!")]
à sua propriedade booleana que faz com que a validação do lado do servidor funcione.Para que a validação do lado do cliente também funcione, eles adicionaram o seguinte 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); } }
fonte
Basta verificar se a representação da string é igual a
True
:[RegularExpression("True")] public bool TermsAndConditions { get; set; }
fonte
RegularExpressionAttribute
usa internamenteConvert.ToString
para obter a representação de string do valor da propriedade (que é entregue a ela como umobject
).Você pode criar seu próprio atributo ou usar CustomValidationAttribute .
É assim que você usaria o CustomValidationAttribute:
[CustomValidation(typeof(BoolValidation), "ValidateBool")]
onde BoolValidation é definido como:
public class BoolValidation { public static ValidationResult ValidateBool(bool boolToBeTrue) { if (boolToBeTrue) { return ValidationResult.Success; } else { return new ValidationResult( "Bool must be true."); } }
fonte
[Required]
atributo significa exigir qualquer valor - pode ser verdadeiro ou falso. Você teria que usar outra validação para isso.fonte
Para ASP.NET Core MVC aqui está a validação de cliente e servidor, com base na solução da 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 então no cliente:
$.validator.addMethod("enforcetrue", function (value, element, param) { return element.checked; }); $.validator.unobtrusive.adapters.addBool("enforcetrue");
Então o uso é:
[EnforceTrue(ErrorMessage = "Please tick the checkbox")] public bool IsAccepted { get; set; }
fonte
$document.ready()
/$(function() { });
".required
atributo na entrada HTML, como:<input asp-for="..." class="..." id="..." type="checkbox" required/>
Continuando a postagem de ta.speot.is e o comentário de Jerad Rose:
A postagem fornecida não funcionará do lado do cliente com validação discreta. Isso deve funcionar em ambos os campos (cliente e servidor):
[RegularExpression("(True|true)")] public bool TermsAndConditions { get; set; }
fonte
regex
método não intrusivo que primeiro verifica se a caixa de seleção é opcional antes de validar o regex, o que faz sentido, exceto que jquery.validate parece considerar qualquer caixa de seleção não marcada como opcional. tl; dr Ele só executa o regex nas caixas de seleção marcadas. Podemos adicionar um shim para oregex
validator
método ou apenas criar um validador personalizado..NET Core MVC - Caixa de seleção obrigatória com anotações de dados
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>
fonte
Não sei como usar DataAnnotations, mas isso é facilmente feito no seu controlador.
public ActionResult Add(Domain.Something model) { if (!model.MyCheckBox) ModelState.AddModelError("MyCheckBox", "You forgot to click accept"); if (ModelState.IsValid) { //'# do your stuff } }
A única outra opção seria construir um validador personalizado para o lado do servidor e um validador remoto para o lado do cliente (a validação remota está disponível apenas em MVC3 +)
fonte
Você tem os itens apropriados configurados no web.config ?
Isso pode fazer com que a validação não funcione.
Você também pode tentar criar um atributo de validação personalizado (uma vez que
[Required]
só se importa se ele existe ou não e você se preocupa com o valor):[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); } }
Então, uso:
[RequiredTrue(ErrorMessage="{0} requires acceptance to continue.")] public bool Agreement {get; set;}
A partir daqui .
fonte
Isto é o que funcionou para mim. Nada mais fez. Mvc 5:
Modelo
public string True { get { return "true"; } } [Required] [Compare("True", ErrorMessage = "Please agree to the Acknowlegement")] public bool Acknowlegement { get; set; }
Visão
@Html.HiddenFor(m => m.True) @Html.EditorFor(model => model.Acknowlegement, new { htmlAttributes = Model.Attributes }) @Html.ValidationMessageFor(model => model.Acknowlegement, "", new { @class = "text-danger" })
fonte
Eu tentei usar a resposta de fields.cage e não funcionou muito bem para mim, mas algo mais simples funcionou, e não tenho certeza exatamente por que (versão diferente do Razor, talvez?), Mas tudo que tive que fazer foi isso:
[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 no arquivo .cshtml:
@Html.CheckBoxFor(m => m.Agreement1Checked) @Html.LabelFor(m => m.Agreement1Checked) @Html.ValidationMessageFor(m => m.Agreement1Checked)
fonte
[NaN, NaN]
onde deveria estar[true, true]
Acho que a melhor maneira de lidar com isso é apenas verificar em seu controlador se a caixa é verdadeira, caso contrário, apenas adicione um erro ao seu modelo e faça com que ele exiba novamente sua visualização.
Como afirmado anteriormente, tudo o que [Requerido] faz é garantir que haja um valor e, no seu caso, se não for verificado, você ainda obterá falso.
fonte
Confira a validação infalível aqui . Você pode baixar / instalar via Nuget.
É uma ótima pequena biblioteca para esse tipo de coisa.
fonte
/// <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 } }; } }
fonte