What approach do you recommend for validating a DateTime on the client side in MVC?
Let's say I have a model with a property named DateOfBirth
that is a DateTime
, like so.
public class UserModel
{
[DataType(DataType.Date)]
public DateTime DateOfBirth {get;set;}
}
On the View, I have a simple
<%: Html.LabelFor(model=>model.DateOfBirth) %>
<%: Html.EditorFor(model=>model.DateOfBirth) %>
<%: Html.ValidationMessageFor(model=>model.DateOfBirth) %>
<input type="submit" value="Submit" />
I can use either the Microsoft MVC validations or the jQuery validations. How do I get the DateTime to validate client-side?
I realize all the DataTypeAttribute does is provide formatting hints and doesn't really do any validation (it leaves that part to the ModelBinder).
Basically I want to duplicate what the ModelBinder does when it tries to put the posted value into the model's DateOfBirth property.
What are your recommendations?
As suggested above, follow Phil Haack's post on custom validations: http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx
Here's how I would do it:
public class DateFormatAttribute : ValidationAttribute {
public override bool IsValid(object value) {
if (value == null) {
return true;
}
// Note: the actual server side validation still has to be implemented :-)
// Just returning true now...
return true;
}
}
public class DateFormatValidator : DataAnnotationsModelValidator
{
string message;
public PriceValidator(ModelMetadata metadata, ControllerContext context
, DateFormatAttribute attribute)
: base(metadata, context, attribute)
{
message = attribute.ErrorMessage;
}
public override IEnumerable GetClientValidationRules()
{
var rule = new ModelClientValidationRule {
ErrorMessage = message,
ValidationType = "date" // note that this string will link to the JavaScript function we'll write later on
};
return new[] { rule };
}
}
DataAnnotationsModelValidatorProvider
.RegisterAdapter(typeof(DateFormatAttribute), typeof(DateFormatValidator));
/*
* Localized default methods for the jQuery validation plugin.
* Locale: NL
*/
jQuery.extend(jQuery.validator.methods, {
date: function(value, element) {
return this.optional(element) || /^\d\d?[\.\/-]\d\d?[\.\/-]\d\d\d?\d?$/.test(value);
}
});
That should cover things...
Josh,
your problem is quite a common problem in MVC, which is that the modelbinder is trying to BIND the inputted values from the form into the model. obviously, if it doesnt 'fit' you'll get an error straight away.
so how do I make the modelbinder use my custom validation? and return my error message?
well, first read and do the things written by phil haack. then you have your custom validation.
the next thing is. dont use Integers and datetimes in your model! If the user can input whatever he wants in a textbox, this always will give problems.
what you should do is, make a flatObject of your object.
a flatObject is pretty simple. It's an object, an exact copy of the variables inside, only, the inst and datetimes are strings (cos those always bind in the modelbinder)
example:
namespace MVC2_NASTEST.Models {
public partial class FlatNieuw {
public int Niw_ID { get; set; }
public string Niw_Datum { get; set; }
public string Niw_Titel { get; set; }
public string Niw_Bericht { get; set; }
public int Niw_Schooljaar { get; set; }
public bool Niw_Publiceren { get; set; }
}
}
the only ints i have are from the dropdowns, cos those dont fail, if the value in the dropdowns are ints. the date (datum) is a string. i do the custom validation on this string. the modelbinder binds to this FlatNieuw object.
my Nieuw class has exactly the same names of fields as this class. so when you are using UpdateModel() this still works. if you are making a new entry, you can use automapper to map this flatObject to your normal Object.
i think this, together with phil haack's blog should give you a hand on how to do this. if you have questions dont hesitate to ask.
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