I have created a custom validation attribute which works server-side (after form is posted) but I cannot get the validation to work client-side.
The custom attribute is:
public class ReasonableAttribute : ValidationAttribute, IClientValidatable
{
public override bool IsValid(object value)
{
return Approval.IsNumberReasonable(value.ToString());
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
ModelClientValidationRule rule = new ModelClientValidationRule();
rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
rule.ValidationType = "reasonable";
yield return rule;
}
}
The IsNumberReasonable()
function just does some checks on the fields input to make sure what they entered could reasonably be an Approval number (e.g. not empty, or "Unknown" or something like that) returning a bool true/false
.
My Model then contains:
[Display(Name = "Approval Number"]
[Reasonable(ErrorMessage = "Please enter a reasonable {0}")]
public String ApprovalNumber { get; set; }
and the View contains:
@Html.LabelFor(model => model.ApprovalNumber, new { @class = "control-label col-md-3" })
<div class="col-md-9 append field">
@Html.TextBoxFor(model => model.ApprovalNumber, new { @class = "input text" })
@Html.ValidationMessageFor(model => model.ApprovalNumber)
</div>
in the JavaScript I have tried adding:
$.validator.unobtrusive.adapters.addBool("reasonable", "required");
// OR
$.validator.unobtrusive.adapters.add("reasonable");
and: (outside of document.ready)
(function ($) {
$.validator.addMethod('reasonable', function (value, element, params) {
return value != '';
}, 'Clientside Should Not Postback');
$.validator.unobtrusive.adapters.addBool('reasonable');
})(jQuery);
in various combinations but have not been able to get it to work.
I have got
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
included in the View.
When the form is submitted, client-side validation works for other fields (required ones etc) but the validation message next to the ApprovalNumber never appears/does not perform my custom validation.
Any pointers in the right direction are appreciated. thanks.
I also have
<configuration>
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
</configuration>
Already in the Web.config file.
Edit 2: as per chenZ's post: The html for the input field is:
<input class="input text valid" data-val="true" data-val-reasonable="Please enter a reasonable Approval Number" data-val-required="Approval Number is Required." id="ApprovalNumber" name="ApprovalNumber" type="text" value="">
Tried updating the bottom of my view with:
<script src="~/Scripts/jquery.validate.js"></script>
<script type="text/javascript">
(function ($) {
$.validator.addMethod('reasonable', function (value, element, params) {
return value != '';
}, 'Clientside Should Not Postback');
})(jQuery);
</script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
<script src="~/Scripts/Create.js"></script>
where the end of jquery.validate.unobtrusive.js
now contains:
$(function () {
$.validator.unobtrusive.adapters.addBool('reasonable');
$("#formID").removeData("unobtrusiveValidation").removeData("validator");
$jQval.unobtrusive.parse(document);
});
}(jQuery));
and create.js
contains:
$.validator.unobtrusive.adapters.addBool("mandatory", "required"); // another custom attribute for checkbox validation
var v = $("#formID").validate({
errorClass: "warning",
onkeyup: false,
onblur: false,
});
the v
variable is used further down for the submit button:
$("#SubmitButton").click(function () {
if (v.form()) {
// The form passed validation so continue..
} else {
// Validation failed, do something else..
}
});
I did some further testing ans it appears to be something to do with the:
(function ($) {
$.validator.addMethod('reasonable', function (value, element, params) {
return value != '';
}, 'Clientside Should Not Postback');
})(jQuery);
when I change it to:
(function ($) {
$.validator.addMethod('reasonable', function (value, element, params) {
return value != 'unknown';
}, 'Clientside Should Not Postback');
})(jQuery);
it works, but only if I type 'unknown' into the input box, anything else passes.. similarly if I put return value != 'jhdsfkhsdkfj';
it only validates when I input jhdsfkhsdkfj.
so it appears that it is using that as the rule? instead of my server-side IsNumberReasonable()
function.
hope that helps in troubleshooting.
I haven't tried it, so I'm not sure, but i think there are 2 places where you may be wrong.
1.rule.ValidationType = "reasonable";
Check your html, find the input and is there an attr data-val-reasonalbe or reasonale
in jquery.validate.unobtrusive.js, line 173, you can find this, so it must be a data-val-xxxx
2.in jquery.validate.unobtrusive.js end of file you can find
so, when the page is loaded, all form set validate
This is a difficult thing. If your code is like
When you do unobtrusive.parse(document); your valid method reasonable doesn't exist, and adapter doesn't exist exist either, so your form valid doesn't have a rule reasonable
If you change the code to like this
the valid method can add, but the $.validator.unobtrusive is undefined
I think you should do more
and put the
in to jquery.validate.unobtrusive.js, and make sure it runs before
I'm not sure if it will work, maybe I'll try later. Hope this can help you.
update I tried it. In point 2, you can use code
Put this code after your add valid method, this will clear valid setting and parse again with your custom rules
update 2
also to unobtrusive.parse(...)
jquery.validate.js line 41
and jquery.validate.unobtrusive.js line 99
when
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
end of this file, called unobtrusive.parse(document), it will append a data to form. If it called before you setup code, the validate setting is without your setup. you can removeData(...), and run unobtrusive.parse(document) by your code again like
validate plugin use data name "validator" and unobtrusive use data name "unobtrusiveValidation".
I'm really sorry for my poor English, hope you can understand.
Add this to your Web.config
Cool then try modifying your rule to use the rule below.
Since I landed here when looking into my issue, I'd like to share that if you're using any 3rd party libraries for controls, such as DevExpress with option embed client libraries, then they may actually re-include the validation scripts, which could lead to your adapter being properly added only to be later lost again. In my case, I had to move my .js file creating the client side unobtrusive validator adapter down below these other offending scripts. I'd also want to either consider dropping my own inclusion of said files, or configuring my 3rd party library not to include them, to prevent such confusion.