I have created a Custom Validation Attribute:
public class FutureDateAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null|| (DateTime)value < DateTime.Now) return false; return true; } }
How can I get this to work on client side too with jquery?
To create a custom validation attributeIn Solution Explorer, right-click the App_Code folder, and then click Add New Item. Under Add New Item, click Class. In the Name box, enter the name of the custom validation attribute class. You can use any name that is not already being used.
Implementing IClientModelValidator interface This method sets certain client side custom data attributes or data-* attributes that are used by the validation system.
When you enter data, the browser and/or the web server will check to see that the data is in the correct format and within the constraints set by the application. Validation done in the browser is called client-side validation, while validation done on the server is called server-side validation.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With