I am attempting to use a custom validation attribute to ensure a checkbox ends up checked. However, the validation error is displaying (not styled) as part of the checkbox's label prior to the validation firing.
To detail:
I have the following property and attribute:
[Display(Name = "TermsAndConditions", ResourceType = typeof(Res.Labels))]
[MustBeTrue(ErrorMessageResourceName = "TermsAndConditionsValidationMessage", ErrorMessageResourceType = typeof(Res.Labels))]
public bool TermsAndConditions { get; set; } = true;
(for whatever reasons. defaulting to true is deliberate. It's swapped back to false on the view):
@model MyModel
@{
MyModel.TermsAndConditions = false;
}
The custom attribute looks like this:
public class MustBeTrueAttribute : ValidationAttribute, IClientValidatable
{
public override bool IsValid(object value)
{
return value is bool && (bool)value;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(Labels.TermsAndConditions),
ValidationType = "mustbetrue"
};
}
}
The HTML in the view looks like this:
<div class="checkbox">
@Html.CheckBoxFor(m => m.TermsAndConditions, true)
<div class="state">
<label for="terms">
@Html.Raw(Label.TermsAndConditions)
@Html.ValidationMessageFor(m => m.TermsAndConditions, Label.TermsAndConditionsValidationMessage)
</label>
</div>
</div>
HTML.Raw is used as I need the label to render an anchor element, I couldn't find another way to do it.
The generated HTML on page load is this:
<div class="checkbox">
<input data-msg-mustbetrue="You must accept the terms and conditions" data-msg-required="The I aceept the <a href="#">terms and conditions</a>. field is required." data-rule-mustbetrue="true" data-rule-required="true" id="TermsAndConditions" name="TermsAndConditions" type="checkbox" value="true">
<input name="TermsAndConditions" type="hidden" value="false">
<div class="state">
<label for="terms">
I aceept the <a href="#">terms and conditions</a>.
<span class="field-validation-valid" data-valmsg-for="TermsAndConditions" data-valmsg-replace="false">You must accept the terms and conditions</span>
</label>
</div>
</div>
After firing the validation, everything works as expected:
<div class="checkbox">
<input data-msg-mustbetrue="You must accept the terms and conditions" data-msg-required="The I aceept the <a href="#">terms and conditions</a>. field is required." data-rule-mustbetrue="true" data-rule-required="true" id="TermsAndConditions" name="TermsAndConditions" type="checkbox" value="true" class="input-validation-error">
<input name="TermsAndConditions" type="hidden" value="false">
<div class="state">
<label for="terms">
I aceept the <a href="#">terms and conditions</a>.
<span class="field-validation-error" data-valmsg-for="TermsAndConditions" data-valmsg-replace="false">You must accept the terms and conditions</span>
</label>
</div>
</div>
I've been banging my head against the wall on and off with this stuff for a while now, can anyone point me in the right direction? Please and thanks.