Date range validation with Entity Framework 4 data annotations - asp.net-mvc

I am using Entity Framework 4 to provide the model for a ASP.NET MVC3 / Razor2 web application. I am using DataAnnotations to implement validation. I need to limit some dates to the range accepted by the SQL smalldatetime type.
My problem is that I can't get the RangeAttribute to work correctly for a date field. The model metadata definition for the field in question is:
[Display(ResourceType = typeof(Resources.Patient), Name = "DateOfBirth_Name")]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
[DataType(DataType.Date)]
[Range(typeof(DateTime), "01/01/1900", "06/06/2079", ErrorMessageResourceType = typeof(Resources.Patient), ErrorMessageResourceName = "DateOfBirth_Range")]
public System.DateTime DateOfBirth { get; set; }
With this code, whatever value I put into the date field, it is treated as invalid by the application. In case its' relevant, I am using the JQuery-UI date picker with the field in question as well.
Can anyone help please?

You do not specify where the error occurs, but my guess is that it is client-side(?) jQuery Validation does not work well with the RangeAttribute. To verify, disable jQuery Validation and the valid input should pass the (server) validation.
To get around this you will have to write your own date range validation, e.g. http://blogs.msdn.com/b/stuartleeks/archive/2011/01/25/asp-net-mvc-3-integrating-with-the-jquery-ui-date-picker-and-adding-a-jquery-validate-date-range-validator.aspx
Alternatively you could look into packages such as Data Annotations Extensions or MVC Foolproof Validation to see if they could be used for solving the problem.

Related

should I remover all [DataType(DataType.Date)] from my models?

I was having a problem where two fields "BattleStartDate" and "BattleEndDate" where not displaying on my edit form, even though the correct vales had been set on the DB when the record was created. The Create and Edit views both use a common partial View _BattleEditFields.
My old model:
[DisplayName("Battle Start Date")]
[Required(ErrorMessage = "Enter date (mm/dd/yyy) when the battle started")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
[DataValidation(ValidationType.RangeValidation, "The battle starting date must be after 1/1/1860 and before 6/1/1865.")]
public DateTime BattleStartDate { get; set; }
[DisplayName("Battle End Date")]
[Required(ErrorMessage = "Enter date (mm/dd/yyy) when the battle ended")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
[DataValidation(ValidationType.RangeValidation, "The battle ending date must be after 1/1/1860 and before 6/1/1865.")]
[DataValidation(ValidationType.CompareDates, "The battle ending date must be equal to or greater than the start date.", compareWith: "BattleStartDate")]
public DateTime BattleEndDate { get; set; }
I noticed that at runtime I got the following error message.
error CS0103: The name 'type' does not exist in the current contex
Once I updated the model to removed the [DataType(DataType.Date)] from both fields, every thing worked fine. I have several other date fields that also have [DataType(DataType.Date)] in the model (see below). Should I just go ahead and remove all of them, even though it does not appear to be causing a problem?? (just have to go back an test the change).
-- these are audit type fields and not displayed to the user --
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime BattleDateAccepted { get; set; }
// --------------------------------------------------------------------------------------------
public string BattleChangedBy { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime BattleDateChange { get; set; }
Normally we would advise against this, but it is advised that you try to follow conventions and patterns in your code, so seeing some Date properties with this attribute and not others can easily lead to confusion, some developers down the track might add it back to those that are missing, other devs might remove it from all of them as you are suggesting here. So this becomes a depends kind of scenario...
Firstly identify why you are using the DataType(DataType.Date) attribute in the first place, in MVC the first reason is usually for validation, however this attribute can also be used in DB ORM libraries that manage your database schema like Entity Framework to ensure that the type of the field in the database should be a Date ONLY data type.
EF has other attributes that can be used for the same purpose, in MVC apps it is common to use a convention to map this attribute to reduce the risk of the two attributes being set with conflicting values.
If you are using an ORM that needs this attribute to manage the database schema, then each of these attributes that you remove may need a corresponding change set elsewhere in your model to ensure that the DB schema is not affected.
This attribute is heavily referenced in MVC validation documentation and is a the minimal configuration for Date input validation. Removing this attribute from the model might still allow invalid values to be accepted through your API, even if the view (due to your other validation attributes) correctly generates the validation in the UI. If your API is not exposed to external callers this may not be a concern to you.
As you have identified that the fields that have this attribute, but are not displayed in the UI do not cause this error you should look into your view code and configuration, to see if you are using a 3rd party control package that is missing a component.
'type' does not exist in the current context is NOT a common error associated with this attribute specifically, but could occur with custom control or UI validation code that references mismatched assemblies, usually a .Net FX UI component in a .Net Core project or vice versa.
In your case, if removing the DataType attribute resolves your error AND has no other adverse effects on your application runtime OR deployment, then remove it. If your model is not exposed through an API to external callers or you would not be letting external callers modify the other fields, then for consistency I would recommend removing this attribute from all the DateTime fields.
Because this is a against the normal MVC expectations for validation, I would include a note about this in your documentation for the model/project so you remember why you have made this decision.
If you have reasons other than validation for keeping the attributes you should investigate further to understand the cause before you apply this to all Date fields in your entire model.

DataAnnotations Date Range

In my MVC4 project I have a Meta class where I have my date format specified with DataAnnotations. I want to limit the range to the SQL DateTime type.
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
[Range(typeof(DateTime), "01/01/1753", "12/31/9999", ErrorMessage = "Check Date")]
public DateTime SeniorityDate
{
get;
set;
}
The format works fine without the range validation. When I add the range validation and I enter an invalid date I get the error message specified. The issues is when I fix the date again to something like 01/27/2008 then the validator still indicates the date is not valid. I assumed this is because I am not entering nor do I want a time component. Is there a way around this issue?
I ended up modifying code listed here to meet my needs.
http://www.headspringlabs.com/blog/mvc-custom-unobtrusive-validator-attribute-date-range-validation/

How is the format for server-side date validation configured in ASP.NET MVC 4?

How is the format for server-side validation of dates in ASP.NET MVC 4 configured? For instance, the following model field ('BirthDate') is only validated according to the format 'MM/dd/yyyy' on the client. On my server, apparently the format 'dd/MM/yyyy' is expected when POST-ed data is bound to the model.
[Required]
[Display(Name = "Date of Birth")]
[DisplayFormat(DataFormatString="{0:MM/dd/yyyy}", ApplyFormatInEditMode=true)]
[DataType(DataType.Date)]
public DateTime BirthDate { get; set; }
The validation of dates on ASP.NET MVC servers is linked to the configured culture. By default, the culture is unspecified and instead the Web client's culture is adopted. So, for instance to make use of US date conventions on the server, edit the configuration/system.web/globalization element of your Web.config as follows (uiCulture shouldn't affect this validation, but I've added it for good measure):
<globalization culture="en-us" uiCulture="en-us"></globalization>

MVC4 validate Date to be today or after?

I have a playlist Model class in MVC4 that has a Date property, and when a user creates it, I want them not to be able to specify a date before today (so today or after).
Here's part of my Playlist class:
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
[Required(ErrorMessage = "Incorrect date format.")]
public DateTime Date { get; set; }
How do I add validation for this "range"? Right now it's only validating to see if it's a valid date, but 11/30/2012 is valid and won't throw up any errors even though it was yesterday.
I'm using Razor for my Views. Thank you.
You can't validate against dynamic values using the Range attribute. You can create your own validator based on ValidationAttribute that validates the date against the current or a calculated date. Or you can use the IValidatableObject interface in your model class (buddy class to stop it getting overwritten by EF), and validate the properties you want there.

Data Annotation Ranges of UK Datetime fields

I want to use Data Annotations to validate DateTime fields, but I'm running into problems. According to documentation on MSDN (http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.rangeattribute.aspx), the following should do the job
[Range(typeof(DateTime), "1/2/2004", "3/4/2004",
ErrorMessage = "Value for {0} must be between {1} and {2}")]
However, this marks any date I enter as invalid!
At first I thought it was not picking up UK dates (when I tried 26/2/2004) but I can't even get it to use dates such as 2/2/2004.
I'm using the dataannotations within MVC2, and using the MicrosoftAjax framework for clientside validation.
Any suggestions?
Thanks
Well, a few years have gone past and I revisited this same issue with MVC4 and I can tell you that it has apparently been resolved.
I created a very simple default MVC4 site, and gave a date member the following attributes
[Required]
[DataType(DataType.Date)]
[Range(typeof(DateTime), "1/2/2004", "3/4/2004", ErrorMessage = "Value for {0} must be between {1} and {2}")]
public DateTime BlogDate { get; set; }
The validation now works perfectly under UK data system, disallowing a date 2/1/2004, allowing a date of 4/3/2004 or 26/3/2004.
The template I was using took advantage of code-first EF4, but I don't have any reason to suspect that it hasn't been fixed generally, since the javascript is working properly too.
So if you are using MVC2 this may still be a problem, but the best solution which I've found is to use MVC4 as long as it is available to you.
As far as i know the RangeAttribute can only validate number on client side, you'll have to write a custom javascript validator for this to work...
check out http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx for an example on how to do this.

Resources