MVC模型要求为true
有没有办法通过数据注释要求布尔属性设置为true?
public class MyAwesomeObj{ public bool ThisMustBeTrue{get;set;} }
你可以创build你自己的validation器:
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 }
我将为Server和Client端创build一个validation器。 使用MVC和不显眼的表单validation,可以简单地通过执行以下操作来实现:
首先,在您的项目中创build一个类来执行服务器端validation,如下所示:
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" }; } }
在此之后,在模型中注释相应的属性:
[EnforceTrue(ErrorMessage=@"Error Message")] public bool ThisMustBeTrue{ get; set; }
最后,通过将以下脚本添加到您的视图来启用客户端validation:
<script type="text/javascript"> jQuery.validator.addMethod("enforcetrue", function (value, element, param) { return element.checked; }); jQuery.validator.unobtrusive.adapters.addBool("enforcetrue"); </script>
注意:我们已经创build了一个方法GetClientValidationRules
,它将注释从我们的模型中推送到视图中。
如果使用资源文件来提供国际化的错误信息,请删除FormatErrorMessage
调用(或者只是调用基础),然后调整GetClientValidationRules
方法,如下所示:
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" }; }
我知道这是一个较旧的post,但想分享一个简单的服务器端的方式来做到这一点。 你创build一个私有属性设置为true,并将你的bool与该属性进行比较。 如果你的布尔没有被选中(默认是false),表单将不会被validation。
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; }
您可以创build自己的属性或使用CustomValidationAttribute 。
这是你将如何使用CustomValidationAttribute:
[CustomValidation(typeof(BoolValidation), "ValidateBool")]
其中BoolValidation被定义为:
public class BoolValidation { public static ValidationResult ValidateBool(bool boolToBeTrue) { if (boolToBeTrue) { return ValidationResult.Success; } else { return new ValidationResult( "Bool must be true."); } }
只要检查它的string表示是否等于True
:
[RegularExpression("True")] public bool TermsAndConditions { get; set; }
[Required]
属性表示需要任何值 – 可以是true或false。 你必须使用另一个validation。
我尝试了几个解决scheme,但没有一个完全为我工作,以获得客户端和服务器端validation。 那么我在MVC 5应用程序中做了什么来实现它:
在您的ViewModel(用于服务器端validation):
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; }
在您的Razor页面(用于客户端validation):
<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>
我只想引导人们到下面的小提琴: https : //dotnetfiddle.net/JbPh0X
用户添加了[Range(typeof(bool), "true", "true", ErrorMessage = "You gotta tick the box!")]
到他们的布尔属性导致服务器端validation工作。
为了也有客户端validation工作,他们添加了以下脚本:
// 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); } }
你有没有在web.config中设置适当的项目 ?
这可能会导致validation不起作用。
你也可以尝试创build一个自定义的validation属性(因为[Required]
只关心它是否存在,而你关心值):
[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); } }
那么,用法:
[RequiredTrue(ErrorMessage="{0} requires acceptance to continue.")] public bool Agreement {get; set;}
从这里 。
我不知道通过DataAnnotations的方式,但是这很容易在您的控制器中完成。
public ActionResult Add(Domain.Something model) { if (!model.MyCheckBox) ModelState.AddModelError("MyCheckBox", "You forgot to click accept"); if (ModelState.IsValid) { //'# do your stuff } }
唯一的其他select是为服务器端构build自定义validation器 ,为客户端构build远程validation器 (远程validation仅在MVC3 +中可用)
我认为处理这个问题的最好办法就是检查你的控制器,如果这个框是真的,否则只要给你的模型添加一个错误,让它重新显示你的视图。
如前所述,所有[必须]确保有一个值,如果没有检查你的情况,你仍然是错误的。
/// ///摘要:-CheckBox for或者inputtypes检查需要validation不起作用的根本原因和解决方法如下/// ///问题:///这个问题的关键在于jQueryvalidation的解释'需要“的规则。 我挖了一点点,并find一个jquery.validate.unobtrusive.js文件中的具体代码:/// adapters.add(“required”,function(options){/// if(options.element.tagName.toUpperCase() !==“INPUT”|| options.element.type.toUpperCase()!==“CHECKBOX”){/// setValidationValues(options,“required”,true); ///} ///}); ///
///修正:(在页面级Jquery脚本修复添加到checkbox所需区域)/// 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:(MVCvalidation的C#代码)///您可以看到它从普通的RequiredAttributeinheritance,而且它实现了IClientValidateable 。这是为了保证规则将传播到客户端(jQueryvalidation)以及。
///注释示例:/// [BooleanRequired] /// public bool iAgree {get; 设置'} ///
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 } }; } }
看看这里的万无一失validation。 你可以通过Nuget下载/安装它。
这是一个伟大的小型图书馆这种事情。
这是为我工作。 没有别的。 Mvc 5:
模型
public string True { get { return "true"; } } [Required] [Compare("True", ErrorMessage = "Please agree to the Acknowlegement")] public bool Acknowlegement { get; set; }
视图
@Html.HiddenFor(m => m.True) @Html.EditorFor(model => model.Acknowlegement, new { htmlAttributes = Model.Attributes }) @Html.ValidationMessageFor(model => model.Acknowlegement, "", new { @class = "text-danger" })
跟随ta.speot.is的post和Jerad Rose的评论:
给定的文章不会在客户端进行不显眼的validation。 这应该在两个阵营中工作:
[RegularExpression("(True|true")] public bool TermsAndConditions { get; set; }