Set property combining 3 MVC dropdowns
I am trying to set the DateTime property Birthday
for a date of birth using 3 dropwdowns for month, day and year in MVC. At the moment, I cannot get a valid ModelState. In addition, the values โโof `model.Birthday. [Month, Day or Year] is not recognized from the mark. Please, help.
My markup looks like this:
@model StatisticalTracker.Models.RegisterModel
...
<li>
@Html.LabelFor(m => m.Birthday)
@Html.DropDownListFor(m => m.Birthday.Month, SelectListItemHelper.GetMonths(), "-- Month --", new { style = "display: inline-block" }) /
@Html.DropDownListFor(m => m.Birthday.Day, SelectListItemHelper.GetDays(), "-- Day --", new { style = "display: inline-block" }) /
@Html.DropDownListFor(m => m.Birthday.Year, SelectListItemHelper.GetYears(), "-- Year --", new { style = "display: inline-block" })
</li>
My ViewModel looks like this:
public class RegisterModel
{
...
[DataType(DataType.Date)]
[Display(Name = "Birthday")]
public DateTime Birthday { get; set; }
}
My account looks like this:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (model.Birthday.Month == 0 || model.Birthday.Day == 0 && model.Birthday.Year == 0)
{
ModelState.AddModelError("Birthday", "Date of birth is required");
}
else
{
DateTime dt = new DateTime(model.Birthday.Year, model.Birthday.Month, model.Birthday.Day);
model.Birthday = dt;
}
if (ModelState.IsValid)
{
...
}
// If we got this far, something failed, redisplay form
return View(model);
}
source to share
You can create HTML helpers for properties with public setters in the model - not for things derived from properties in the model. Since Ric Notes - DateTime.Year / .Month / .Day properties are readonly and therefore cannot be linked.
What you need to do is create a new view model:
public class RegisterModel
{
...
[Display(Name = "Birthday Year")]
public int BirthdayYear { get; set; }
[Display(Name = "Birthday Month")]
public int BirthdayMonth { get; set; }
[Display(Name = "Birthday Day")]
public int BirthdayDay { get; set; }
}
If you want to perform validation to make sure the date is valid (i.e. to ensure that they cannot pick the 29th month during a non-leap year, etc.), you will need a special validation attribute - this article looks like pretty good: http://dotnetspeak.com/2012/05/validating-dependent-fields-in-asp-net-mvc
An easier approach if you only need server side validation is to implement IValidateableObject
in your model class - eg: http://weblogs.asp.net/scottgu/class-level-model-validation-with-ef-code-first -and-asp-net-mvc-3
As an alternative approach - you can just have one date field - but add a client side date picker - jQuery UI . well. (HTML5 <input type="Date">
is another approach, but you cannot guarantee that all of its clients support it)
One of the last options is to use a property <input type="hidden">
for the Date of Birth property , and on the client side javascript is tied to dropdowns which updates the hidden field when each dropdown changes.
source to share