Gibt es eine Möglichkeit durch Datenanmerkungen, dass eine boolesche Eigenschaft auf true gesetzt werden muss?
public class MyAwesomeObj{
public bool ThisMustBeTrue{get;set;}
}
Gibt es eine Möglichkeit durch Datenanmerkungen, dass eine boolesche Eigenschaft auf true gesetzt werden muss?
public class MyAwesomeObj{
public bool ThisMustBeTrue{get;set;}
}
Antworten:
Sie können Ihren eigenen Validator erstellen:
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;
Dies ist ein redundanter Vergleich
Ich würde einen Validator sowohl für die Server- als auch für die Clientseite erstellen. Mit MVC und unauffälliger Formularvalidierung kann dies einfach durch Folgendes erreicht werden:
Erstellen Sie zunächst eine Klasse in Ihrem Projekt, um die serverseitige Validierung wie folgt durchzuführen:
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"
};
}
}
Kommentieren Sie anschließend die entsprechende Eigenschaft in Ihrem Modell:
[EnforceTrue(ErrorMessage=@"Error Message")]
public bool ThisMustBeTrue{ get; set; }
Aktivieren Sie schließlich die clientseitige Validierung, indem Sie Ihrer Ansicht das folgende Skript hinzufügen:
<script type="text/javascript">
jQuery.validator.addMethod("enforcetrue", function (value, element, param) {
return element.checked;
});
jQuery.validator.unobtrusive.adapters.addBool("enforcetrue");
</script>
Hinweis: Wir haben bereits eine Methode erstellt, mit GetClientValidationRules
der unsere Anmerkung aus unserem Modell in die Ansicht verschoben wird.
Wenn Sie Ressourcendateien verwenden, um die Fehlermeldung für die Internationalisierung bereitzustellen, entfernen Sie den FormatErrorMessage
Aufruf (oder rufen Sie einfach die Basis auf) und optimieren Sie die GetClientValidationRules
Methode wie folgt :
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"
};
}
Ich weiß, dass dies ein älterer Beitrag ist, wollte aber einen einfachen serverseitigen Weg teilen, um dies zu tun. Sie erstellen eine öffentliche Eigenschaft, die auf true festgelegt ist, und vergleichen Ihren Bool mit dieser Eigenschaft. Wenn Ihr Bool nicht aktiviert ist (standardmäßig false), wird das Formular nicht überprüft.
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; }
Rasiermessercode
@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)
Ich habe mehrere Lösungen ausprobiert, aber keine davon hat für mich vollständig funktioniert, um sowohl eine clientseitige als auch eine serverseitige Validierung zu erhalten. Also, was ich in meiner MVC 5-Anwendung getan habe, um sie zum Laufen zu bringen:
In Ihrem ViewModel (zur serverseitigen Validierung):
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; }
Auf Ihrer Razor-Seite (zur clientseitigen Validierung):
<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>
Ich möchte die Leute nur auf die folgende Geige hinweisen: https://dotnetfiddle.net/JbPh0X
Der Benutzer hat [Range(typeof(bool), "true", "true", ErrorMessage = "You gotta tick the box!")]
seiner booleschen Eigenschaft hinzugefügt
, wodurch die serverseitige Validierung funktioniert.
Damit auch die clientseitige Validierung funktioniert, haben sie das folgende Skript hinzugefügt:
// 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);
}
}
Überprüfen Sie einfach, ob die Zeichenfolgendarstellung gleich ist True
:
[RegularExpression("True")]
public bool TermsAndConditions { get; set; }
RegularExpressionAttribute
Wird intern verwendet Convert.ToString
, um die Zeichenfolgendarstellung des Werts der Eigenschaft abzurufen (der als übergeben wird object
).
[Required]
Attribut steht für das Erfordernis eines beliebigen Wertes - es kann entweder wahr oder falsch sein. Dafür müssten Sie eine andere Validierung verwenden.
Sie können entweder Ihr eigenes Attribut erstellen oder das CustomValidationAttribute verwenden .
So würden Sie das CustomValidationAttribute verwenden:
[CustomValidation(typeof(BoolValidation), "ValidateBool")]
Dabei ist BoolValidation definiert als:
public class BoolValidation
{
public static ValidationResult ValidateBool(bool boolToBeTrue)
{
if (boolToBeTrue)
{
return ValidationResult.Success;
}
else
{
return new ValidationResult(
"Bool must be true.");
}
}
Weiterverfolgung des Beitrags von ta.speot.is und des Kommentars von Jerad Rose:
Der angegebene Beitrag funktioniert nicht clientseitig mit unauffälliger Validierung. Dies sollte in beiden Lagern (Client & Server) funktionieren:
[RegularExpression("(True|true)")]
public bool TermsAndConditions { get; set; }
regex
Methode unauffällig definiert, dass zuerst überprüft wird, ob das Kontrollkästchen optional ist, bevor der reguläre Ausdruck überprüft wird. Dies ist sinnvoll, mit der Ausnahme, dass jquery.validate jedes nicht aktivierte Kontrollkästchen als optional betrachtet. tl; dr Es wird die Regex nur für aktivierte Kontrollkästchen ausgeführt. Wir können einen Shim für die regex
validator
Methode hinzufügen oder einfach einen benutzerdefinierten Validator erstellen.
Haben Sie die entsprechenden Elemente in der web.config eingerichtet ?
Dies könnte dazu führen, dass die Validierung nicht funktioniert.
Sie können auch versuchen, ein benutzerdefiniertes Validierungsattribut zu erstellen (da es [Required]
nur darum geht, ob es vorhanden ist oder nicht, und Sie sich um den Wert kümmern):
[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);
}
}
Dann Verwendung:
[RequiredTrue(ErrorMessage="{0} requires acceptance to continue.")]
public bool Agreement {get; set;}
Von hier aus .
Für ASP.NET Core MVC gibt es hier eine Client- und Server-Validierung, die auf der Lösung von dazbradbury basiert
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);
}
}
Und dann auf dem Client:
$.validator.addMethod("enforcetrue", function (value, element, param) {
return element.checked;
});
$.validator.unobtrusive.adapters.addBool("enforcetrue");
Dann ist die Verwendung:
[EnforceTrue(ErrorMessage = "Please tick the checkbox")]
public bool IsAccepted { get; set; }
.NET Core MVC - Erforderliches Kontrollkästchen mit Datenanmerkungen
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>
Ich kenne keinen Weg durch DataAnnotations, aber dies ist in Ihrem Controller einfach möglich.
public ActionResult Add(Domain.Something model)
{
if (!model.MyCheckBox)
ModelState.AddModelError("MyCheckBox", "You forgot to click accept");
if (ModelState.IsValid) {
//'# do your stuff
}
}
Die einzige andere Möglichkeit wäre, einen benutzerdefinierten Validator für die Serverseite und einen Remote-Validator für die Client-Seite zu erstellen (Remote-Validierung ist nur in MVC3 + verfügbar).
Das hat bei mir funktioniert. Sonst nichts. Mvc 5:
Modell
public string True
{
get
{
return "true";
}
}
[Required]
[Compare("True", ErrorMessage = "Please agree to the Acknowlegement")]
public bool Acknowlegement { get; set; }
Aussicht
@Html.HiddenFor(m => m.True)
@Html.EditorFor(model => model.Acknowlegement, new { htmlAttributes = Model.Attributes })
@Html.ValidationMessageFor(model => model.Acknowlegement, "", new { @class = "text-danger" })
Ich denke, der beste Weg, dies zu handhaben, besteht darin, einfach in Ihrem Controller zu überprüfen, ob das Kästchen wahr ist. Andernfalls fügen Sie Ihrem Modell einfach einen Fehler hinzu und lassen Sie es Ihre Ansicht erneut anzeigen.
Wie bereits erwähnt, muss [Erforderlich] nur sicherstellen, dass ein Wert vorhanden ist. Wenn dies nicht aktiviert ist, werden Sie immer noch falsch angezeigt.
/// <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 } };
}
}
Ich habe versucht, die Antwort von fields.cage zu verwenden, und es hat bei mir nicht ganz funktioniert, aber etwas Einfacheres hat funktioniert, und ich bin mir nicht sicher, warum (vielleicht eine andere Razor-Version?), Aber alles, was ich tun musste, war Folgendes:
[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; }
Und in der .cshtml-Datei:
@Html.CheckBoxFor(m => m.Agreement1Checked)
@Html.LabelFor(m => m.Agreement1Checked)
@Html.ValidationMessageFor(m => m.Agreement1Checked)
[NaN, NaN]
wo er sein sollte[true, true]