I have a view model that has year/month/day properties for someone's date of birth. All of these fields are required. Right now, if someone doesn't enter anything for the date of birth they get 3 separate error messages.
What I want to do is somehow group those error messages together into 1 message that just says 'Date of birth is required'. So if 1 or more of those fields are blank, they will always just get the 1 validation message.
I NEED this to work on client-side validation via jquery validate and unobtrusive validate. I know this is possible with the jquery validate plugin by looking at this question. But I don't know how to achieve this with asp.net mvc using validation attributes on my model and unobtrusive validation. Hopefully there's some built in way to group properties for validation purposes, but if not can this be done with a custom validation attribute?
Here's what my existing model and view looks like:
The Model:
public class MyModel {
[Required(ErrorMessage = "Year is required")]
public int Year { get; set; }
[Required(ErrorMessage = "Month is required")]
public int Month { get; set; }
[Required(ErrorMessage = "Day is required")]
public int Day { get; set; }
}
The View:
<div>
<label>Date of birth: <span style="color:red;">*</span></label>
<div>@Html.DropDownListFor(m => m.Year, ApplicationModel.GetSelectListForDateRange(DateTime.Today.Year - 16, DateTime.Today.Year - 10), "", new{data_description="birthDate"})@Html.LabelFor(m => m.StudentBirthYear)</div>
<div>@Html.DropDownListFor(m => m.Month, ApplicationModel.GetSelectListForDateRange(1, 12, true), "", new{data_description="birthDate"})@Html.LabelFor(m => m.StudentBirthMonth)</div>
<div>@Html.DropDownListFor(m => m.Day, ApplicationModel.GetSelectListForDateRange(1, 31), "", new{data_description="birthDate"})@Html.LabelFor(m => m.StudentBirthDay)</div>
</div>
<div class="error-container">@Html.ValidationMessageFor(m => m.Year)</div>
<div class="error-container">@Html.ValidationMessageFor(m => m.Month)</div>
<div class="error-container">@Html.ValidationMessageFor(m => m.Day)</div>
You should implement
IValidatableObject
and take of theRequire
. Then the validation on the server side will do the job, something like:For client side validation you need to implement your own function, and prompt the error to the user somehow.
EDIT: Given that you still need client side validation, you should do something like this:
You could do that simply using CustomAttribute.
Just put this attribute on your model
and then simply define the rules to validate the values in the following method:
For more information, you could visit this link.
I am somewhat late to the party (only couple of years) still...
Most appropriate solution is indeed creating a
CustomAttribute
but instead of giving you good advice an leaving to die I will show you how.Custom Attribute:
ViewModel: Decorate only one field on your viewModel like following:
Jquery: You will need to add adapters in my case it's
jquery.validate.unobtrusive.customadapters.js
or wherever you register your adapters (you might put this on the page just do it after unobtrusive validation runs).and that should do it.
For those who are interested what this does: In C# land it grabs the ids of fields glues them with
,
and puts into custom attribute on Year field.HTML should look something like this (If it doesn't debug C# attribute):
Then Jquery validation splits them back into id's and checks if all of them are not empty and that's pretty much it.
You will want to mark fields as invalid somehow (now it would only mark the field attribute is sitting on) most appropriate solution IMHO is to wrap all fields in container with class
field-error-wrapper
and then add following to your page after Jquery validation is loaded:instead of marking field it will mark container and then you can write your css in a way that if container is marked with
.input-validation-error
then all fields inside turn red. I think my job here is done.EDIT: Ok so there appears to be one more issue where fields get unmarked because validator thinks that day and month are valid and it needs to remove invalid class from parent, validator first marks invalid fields then unmarks valid which causes validation not to get highlighted, so I changed the sequence in which validation happens, I wouldn't recommend overriding this globally (cause I am not sure on what catastrophic side affects it might have) just paste it on the page where you have birthdate fields.
Hope this saves you some time.
Hi I hope this fulfill your requirement
Here is Running Example