Most of us probably writing a lot of java script for doing
the validation in the client side. That should not be the best practice when
you work with huge applications. Here I have tried to implement a generic
validation expression custom validator which does the most of your effort. Also
the message can be handled in the server side not in the client side. $.data(element.form,
'validator').settings collection allows you to customize the message in the
client side.
The below example I have parsed the string in the client
side which calculates the Price1 and Price2 and show up in the screen with the
error message.
I have defined a model as below.
public class PriceModel
{
[Display(Name = "Id")]
public int Id { get; set; }
[Display(Name = "First
Price")]
[Required(ErrorMessage="Required")]
public double Price1
{ get; set; }
[Display(Name = "Second
Price")]
[Required(ErrorMessage = "Required")]
public double Price2
{ get; set; }
[Display(Name = "Total
Price")]
[Required(ErrorMessage = "Required")]
[EvalExpression(Expression = "parseFloat(Price1.value) +
parseFloat(Price2.value)", Operator = "<",
ErrorMessage = "$.validator.format(\"Total
price should be greater than {0}\", parseFloat(Price1.value) +
parseFloat(Price2.value))")]
public double
TotalPrice { get; set;
}
}
Also I have created the script page as below to register the
new eval expression message at client side.
<script type="text/javascript">
function htmlUnescape(value) {
return String(value)
.replace(/"/g, '"')
.replace(/'/g, "'")
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/&/g, '&');
}
//custom validation rule - checkAge
$.validator.addMethod("expressionvalidator",
function (value, element, params) {
var expressionValue =
eval(params.evalexpression).toString();
var existingMessage = htmlUnescape($(element).attr('data-val-expressionvalidator').toString());
if (existingMessage.indexOf("{"))
// if really required
{
$.data(element.form, 'validator').settings.messages[element.id]["expressionvalidator"] =
eval(existingMessage).toString();
}
// if the value is not a number, probably we can ignore
if (expressionValue == "NaN")
return true;
if (eval(expressionValue + params.evaloperator +
value))
return true;
else
return false;
}, '');
$.validator.unobtrusive.adapters.add('expressionvalidator',
['evalexpression', 'evaloperator'],
function (options) {
options.rules["expressionvalidator"]
= options.params;
options.messages["expressionvalidator"]
= options.message;
});
</script>
The cshtml view tags provided below.
@using (Html.BeginForm())
{
@Html.ValidationSummary(true,"Invalid
data")
<div>
<fieldset>
<legend>Price</legend>
<table>
<tr>
<td>
@Html.LabelFor(model => model.Id)
</td>
<td>
@Html.TextBoxFor(model => model.Id)
@Html.ValidationMessageFor(model =>
model.Id)
</td>
</tr>
<tr>
<td>
@Html.LabelFor(model => model.Price1)
</td>
<td>
@Html.TextBoxFor(model => model.Price1)
@Html.ValidationMessageFor(model =>
model.Price1)
</td>
</tr>
<tr>
<td>
@Html.LabelFor(model => model.Price2)
</td>
<td>
@Html.TextBoxFor(model => model.Price2)
@Html.ValidationMessageFor(model =>
model.Price2)
</td>
</tr>
<tr>
<td>
@Html.LabelFor(model =>
model.TotalPrice)
</td>
<td>
@Html.TextBoxFor(model =>
model.TotalPrice)
@Html.ValidationMessageFor(model =>
model.TotalPrice)
</td>
</tr>
</table>
<p>
<input
type="submit"
value="Submit"
/>
</p>
</fieldset>
</div>
}
In the output you can see the validation as below.
