Perform client side validation for custom attribute Perform client side validation for custom attribute jquery jquery

Perform client side validation for custom attribute


Here's how to proceed:

Start by defining the custom validation attribute:

public class FutureDateAttribute : ValidationAttribute, IClientValidatable{    public override bool IsValid(object value)    {        if (value == null || (DateTime)value < DateTime.Now)            return false;        return true;    }    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)    {        yield return new ModelClientValidationRule        {            ErrorMessage = this.ErrorMessage,            ValidationType = "futuredate"        };    }}

Notice how it implements IClientValidatable. Next we write our model:

public class MyViewModel{    [FutureDate(ErrorMessage = "Should be in the future")]    public DateTime Date { get; set; }}

Then a controller:

public class HomeController : Controller{    public ActionResult Index()    {        return View(new MyViewModel        {            // intentionally put in the past            Date = DateTime.Now.AddDays(-1)        });    }    [HttpPost]    public ActionResult Index(MyViewModel model)    {        return View(model);    }}

and finally a view:

@using (Html.BeginForm()){    @Html.LabelFor(x => x.Date)    @Html.TextBoxFor(x => x.Date)    @Html.ValidationMessageFor(x => x.Date)    <input type="submit" value="OK" />}

The last part for the magic to happen is to define the custom adapter:

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script><script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script><script type="text/javascript">    // we add a custom jquery validation method    jQuery.validator.addMethod('greaterThan', function (value, element, params) {        if (!/Invalid|NaN/.test(new Date(value))) {            return new Date(value) > new Date($(params).val());        }        return isNaN(value) && isNaN($(params).val()) || (parseFloat(value) > parseFloat($(params).val()));    }, '');    // and an unobtrusive adapter    jQuery.validator.unobtrusive.adapters.add('futuredate', { }, function (options) {        options.rules['greaterThan'] = true;        options.messages['greaterThan'] = options.message;    });</script>


It took a little while since your question was asked, but if you still like metadata, and you're still open for simplified alternatives, you can solve your problem using following annotations:

[Required][AssertThat("Date > Now()")]public DateTime? Date { get; set; }

It works for both - server and client, out of the box. For further details take a look at ExpressiveAnnotations library.