是否有办法通过数据注释要求将布尔属性设置为true?
public class MyAwesomeObj{
public bool ThisMustBeTrue{get;set;}
}
答案 0 :(得分:124)
我会为服务器端和客户端创建验证器。使用MVC和不显眼的表单验证,只需执行以下操作即可实现:
首先,在项目中创建一个类来执行服务器端验证,如下所示:
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; }
最后,通过在View中添加以下脚本来启用客户端验证:
<script type="text/javascript">
jQuery.validator.addMethod("enforcetrue", function (value, element, param) {
return element.checked;
});
jQuery.validator.unobtrusive.adapters.addBool("enforcetrue");
</script>
注意:我们已经创建了一个方法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"
};
}
答案 1 :(得分:77)
我知道这是一篇较旧的帖子,但想分享一个简单的服务器方式来做到这一点。您创建一个设置为true的公共属性,并将您的bool与该属性进行比较。如果未检查您的bool(默认为false),表单将无法验证。
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; }
答案 2 :(得分:46)
您可以创建自己的验证器:
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
}
答案 3 :(得分:11)
我尝试了几种解决方案,但它们都没有完全为我提供客户端和服务器端验证。所以我在MVC 5应用程序中做了什么让它工作:
在您的ViewModel中(用于服务器端验证):
GetCommandLineA()
在您的Razor页面中(用于客户端验证):
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; }
答案 4 :(得分:8)
我想将人们引导到以下小提琴:https://dotnetfiddle.net/JbPh0X
用户添加了
[Range(typeof(bool), "true", "true", ErrorMessage = "You gotta tick the box!")]
到他们的布尔属性,这会导致服务器端验证工作。
为了使客户端验证工作,他们添加了以下脚本:
// 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);
}
}
答案 5 :(得分:6)
只需检查其字符串表示是否等于True
:
[RegularExpression("True")]
public bool TermsAndConditions { get; set; }
答案 6 :(得分:5)
您可以创建自己的属性,也可以使用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.");
}
}
答案 7 :(得分:5)
[Required]
属性代表要求任何值 - 它可以是true或false。你必须使用另一个验证。
答案 8 :(得分:2)
你有appropriate items set up in the web.config吗?
这可能导致验证失效。
您还可以尝试创建自定义验证属性(因为[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;}
来自here。
答案 9 :(得分:2)
关注ta.speot.is的帖子以及Jerad Rose的评论:
给定的帖子不会在客户端使用不显眼的验证。 这应该适用于两个阵营(客户端和服务器):
<div class="checkboxAndLabel">
<input type="checkbox" id="{{shape.id}}" name="checkbox"
ng-model="shape.isSelected" ng-click="controller.addOrRemoveShape(shape)"/>
<label for="{{shape.id}}"></label>
</div>
答案 10 :(得分:2)
对于 ASP.NET Core MVC ,这是基于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);
}
}
然后在客户端上:
$.validator.addMethod("enforcetrue", function (value, element, param) {
return element.checked;
});
$.validator.unobtrusive.adapters.addBool("enforcetrue");
那么用法是:
[EnforceTrue(ErrorMessage = "Please tick the checkbox")]
public bool IsAccepted { get; set; }
答案 11 :(得分:1)
我不知道通过DataAnnotations的方法,但这很容易在您的控制器中完成。
public ActionResult Add(Domain.Something model)
{
if (!model.MyCheckBox)
ModelState.AddModelError("MyCheckBox", "You forgot to click accept");
if (ModelState.IsValid) {
//'# do your stuff
}
}
唯一的另一个选择是为服务器端构建自定义验证器,为客户端构建remote validator(远程验证仅在MVC3 +中可用)
答案 12 :(得分:1)
我尝试使用fields.cage的答案,但它对我而言并不奏效,但做了一些简单的事情,而且我不确定为什么(不同的Razor版本?),但是我要做的就是这个:
[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; }
在.cshtml文件中:
@Html.CheckBoxFor(m => m.Agreement1Checked)
@Html.LabelFor(m => m.Agreement1Checked)
@Html.ValidationMessageFor(m => m.Agreement1Checked)
答案 13 :(得分:0)
我认为处理此问题的最佳方法是检查控制器是否为真,否则只需在模型中添加错误并重新显示视图即可。
如前所述,所有[必需]确实存在一个值,如果没有检查,你仍然会得到错误。
答案 14 :(得分:0)
/// <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 } };
}
}
答案 15 :(得分:0)
.NET Core MVC-带有数据注释的必需复选框
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>