Is there a way through data annotations to require that a boolean property be set to true?
public class MyAwesomeObj{ public bool ThisMustBeTrue{get;set;} }
I would create a validator for both Server AND Client side. Using MVC and unobtrusive form validation, this can be achieved simply by doing the following:
Firstly, create a class in your project to perform the server side validation like so:
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" }; } }
Following this, annotate the appropriate property in your model:
[EnforceTrue(ErrorMessage=@"Error Message")] public bool ThisMustBeTrue{ get; set; }
And Finally, enable client side validation by adding the following script to your View:
<script type="text/javascript"> jQuery.validator.addMethod("enforcetrue", function (value, element, param) { return element.checked; }); jQuery.validator.unobtrusive.adapters.addBool("enforcetrue"); </script>
Note: We already created a method GetClientValidationRules
which pushes our annotation to the view from our model.
If using resource files to supply the error message for internationalization, remove the FormatErrorMessage
call (or just call the base) and tweak the GetClientValidationRules
method like so:
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" }; }
I know this is an older post but wanted to share a simple server side way to do this. You create a public property set to true and compare your bool to that property. If your bool is not checked (by default false) the form will not validate.
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; }
Razor code
@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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With