Có cách nào thông qua chú thích dữ liệu để yêu cầu thuộc tính boolean được đặt thành true không?
public class MyAwesomeObj{
public bool ThisMustBeTrue{get;set;}
}
Có cách nào thông qua chú thích dữ liệu để yêu cầu thuộc tính boolean được đặt thành true không?
public class MyAwesomeObj{
public bool ThisMustBeTrue{get;set;}
}
Câu trả lời:
Bạn có thể tạo trình xác thực của riêng mình:
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;
đây là một so sánh thừa
Tôi sẽ tạo trình xác thực cho cả phía Máy chủ VÀ Máy khách. Sử dụng MVC và xác thực biểu mẫu không phô trương, điều này có thể đạt được chỉ đơn giản bằng cách thực hiện như sau:
Trước tiên, hãy tạo một lớp trong dự án của bạn để thực hiện xác thực phía máy chủ như sau:
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"
};
}
}
Sau đây, chú thích thuộc tính thích hợp trong mô hình của bạn:
[EnforceTrue(ErrorMessage=@"Error Message")]
public bool ThisMustBeTrue{ get; set; }
Và Cuối cùng, bật xác thực phía máy khách bằng cách thêm tập lệnh sau vào Chế độ xem của bạn:
<script type="text/javascript">
jQuery.validator.addMethod("enforcetrue", function (value, element, param) {
return element.checked;
});
jQuery.validator.unobtrusive.adapters.addBool("enforcetrue");
</script>
Lưu ý: Chúng tôi đã tạo một phương thức GetClientValidationRules
đẩy chú thích của chúng tôi đến chế độ xem từ mô hình của chúng tôi.
Nếu sử dụng tệp tài nguyên để cung cấp thông báo lỗi cho quá trình quốc tế hóa, hãy loại bỏ FormatErrorMessage
cuộc gọi (hoặc chỉ gọi cơ sở) và chỉnh sửa GetClientValidationRules
phương thức như sau:
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"
};
}
Tôi biết đây là một bài đăng cũ hơn nhưng muốn chia sẻ một cách đơn giản phía máy chủ để thực hiện việc này. Bạn tạo thuộc tính công cộng được đặt thành true và so sánh bool của bạn với thuộc tính đó. Nếu bool của bạn không được chọn (theo mặc định là false) thì biểu mẫu sẽ không hợp lệ.
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; }
Mã dao cạo
@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)
Tôi đã thử một số giải pháp nhưng không có giải pháp nào hoạt động hoàn toàn để tôi có được xác thực cả phía máy khách và máy chủ. Vì vậy, những gì tôi đã làm trong ứng dụng MVC 5 của mình để nó hoạt động:
Trong ViewModel của bạn (để xác thực phía máy chủ):
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; }
Trong trang Razor của bạn (để xác thực phía khách hàng):
<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>
Tôi chỉ muốn hướng mọi người đến Fiddle sau: https://dotnetfiddle.net/JbPh0X
Người dùng đã thêm
[Range(typeof(bool), "true", "true", ErrorMessage = "You gotta tick the box!")]
vào thuộc tính boolean của họ để xác thực phía máy chủ hoạt động.
Để xác thực phía máy khách cũng hoạt động, họ đã thêm tập lệnh sau:
// 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);
}
}
Chỉ cần kiểm tra xem liệu biểu diễn chuỗi của nó có bằng True
:
[RegularExpression("True")]
public bool TermsAndConditions { get; set; }
RegularExpressionAttribute
sử dụng nội bộ Convert.ToString
để lấy biểu diễn chuỗi giá trị của thuộc tính (được phân phối đến nó dưới dạng một object
).
Bạn có thể tạo thuộc tính của riêng mình hoặc sử dụng CustomValidationAttribute .
Đây là cách bạn sẽ sử dụng CustomValidationAttribute:
[CustomValidation(typeof(BoolValidation), "ValidateBool")]
trong đó BoolValidation được định nghĩa là:
public class BoolValidation
{
public static ValidationResult ValidateBool(bool boolToBeTrue)
{
if (boolToBeTrue)
{
return ValidationResult.Success;
}
else
{
return new ValidationResult(
"Bool must be true.");
}
}
[Required]
thuộc tính là viết tắt của việc yêu cầu bất kỳ giá trị nào - nó có thể là true hoặc false. Bạn sẽ phải sử dụng một xác thực khác cho điều đó.
Theo dõi bài đăng của ta.speot.is và nhận xét từ Jerad Rose:
Bài đăng đã cho sẽ không hoạt động ở phía máy khách với xác thực không phô trương. Điều này sẽ hoạt động ở cả hai bên (máy khách và máy chủ):
[RegularExpression("(True|true)")]
public bool TermsAndConditions { get; set; }
regex
phương pháp xác định không phô trương trước tiên kiểm tra xem hộp kiểm có phải là tùy chọn hay không trước khi xác thực regex, điều này có ý nghĩa, ngoại trừ jquery.validate dường như coi bất kỳ hộp kiểm nào chưa được chọn là tùy chọn. tl; dr Nó chỉ chạy regex trên các hộp kiểm đã chọn. Chúng ta có thể thêm một miếng đệm cho regex
validator
phương thức hoặc chỉ tạo một trình xác thực tùy chỉnh.
.NET Core MVC - Hộp kiểm bắt buộc có chú thích dữ liệu
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>
Tôi không biết có cách nào thông qua DataAnnotations, nhưng điều này có thể dễ dàng thực hiện trong bộ điều khiển của bạn.
public ActionResult Add(Domain.Something model)
{
if (!model.MyCheckBox)
ModelState.AddModelError("MyCheckBox", "You forgot to click accept");
if (ModelState.IsValid) {
//'# do your stuff
}
}
Tùy chọn khác duy nhất sẽ là xây dựng trình xác thực tùy chỉnh cho phía máy chủ và trình xác thực từ xa cho phía máy khách (xác thực từ xa chỉ khả dụng trong MVC3 +)
Bạn đã thiết lập các mục thích hợp trong web.config chưa không?
Điều đó có thể khiến xác thực không hoạt động.
Bạn cũng có thể cố gắng tạo thuộc tính xác thực tùy chỉnh (vì [Required]
chỉ quan tâm đến việc nó có tồn tại hay không và bạn quan tâm đến giá trị):
[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);
}
}
Sau đó, cách sử dụng:
[RequiredTrue(ErrorMessage="{0} requires acceptance to continue.")]
public bool Agreement {get; set;}
Từ đây .
Đây là những gì làm việc cho tôi. Không có gì khác đã làm. Mvc 5:
Mô hình
public string True
{
get
{
return "true";
}
}
[Required]
[Compare("True", ErrorMessage = "Please agree to the Acknowlegement")]
public bool Acknowlegement { get; set; }
Lượt xem
@Html.HiddenFor(m => m.True)
@Html.EditorFor(model => model.Acknowlegement, new { htmlAttributes = Model.Attributes })
@Html.ValidationMessageFor(model => model.Acknowlegement, "", new { @class = "text-danger" })
Đối với ASP.NET Core MVC ở đây là xác thực máy khách và máy chủ, dựa trên giải pháp của 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);
}
}
Và sau đó trên máy khách:
$.validator.addMethod("enforcetrue", function (value, element, param) {
return element.checked;
});
$.validator.unobtrusive.adapters.addBool("enforcetrue");
Sau đó, cách sử dụng là:
[EnforceTrue(ErrorMessage = "Please tick the checkbox")]
public bool IsAccepted { get; set; }
Tôi đã cố gắng sử dụng câu trả lời của fields.cage và nó không hoàn toàn phù hợp với tôi, nhưng một cái gì đó đơn giản hơn đã xảy ra và tôi không chắc chính xác tại sao (có thể là phiên bản Razor khác?), Nhưng tất cả những gì tôi phải làm là:
[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; }
Và trong tệp .cshtml:
@Html.CheckBoxFor(m => m.Agreement1Checked)
@Html.LabelFor(m => m.Agreement1Checked)
@Html.ValidationMessageFor(m => m.Agreement1Checked)
[NaN, NaN]
ở nơi nó phải ở[true, true]
Tôi nghĩ rằng cách tốt nhất để xử lý điều này là chỉ cần kiểm tra trong bộ điều khiển của bạn nếu hộp là đúng, nếu không chỉ cần thêm lỗi vào mô hình của bạn và để nó hiển thị lại chế độ xem của bạn.
Như đã nêu trước đây, tất cả [Bắt buộc] làm là đảm bảo có một giá trị và trong trường hợp của bạn nếu không được chọn, bạn vẫn nhận được sai.
/// <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 } };
}
}