Search code examples
c#asp.net-mvcdatetimeasp.net-validators

ASP.NET MVC Model bindING separate day, month, year string fields to single DateTime object


I am currently building a form that requires the user to enter their date of birth. I have determined that the most user friendly way to do this is through separate date day, month, and year input fields.

I have a strongly typed view that contains text boxes for birth day, birth month, and birth year. Once the form is posted to the server I require these posted string values to be converted to a proper DateTime object. I am currently generating this DateTime object in my custom validator that performs age validation tests however I believe there is a far better approach.

So far I have tried building the DateTime object in the model constructor as follows:

public class Applicant
{
    [Required(ErrorMessage = "Day Required")]
    public string DobDay { get; set; }
    [Required(ErrorMessage = "Month Required")]
    public string DobMonth { get; set; }
    [Required(ErrorMessage = "Year Required")]
    [BirthDateValidation("DobDay", "DobMonth")]
    public string DobYear { get; set; }

    public DateTime BirthDate { get; set; }

    public Applicant()
    {
        this.BirthDate = new DateTime(Convert.ToInt32(this.DobYear), Convert.ToInt32(this.DobMonth), Convert.ToInt32(this.DobDay));
    }
}

Is there a way to make this task more automated, as I have tried above, so that when the form is posted to the server a DateTime object is automatically built using the posted birth day, birth month, birth year form values?


Solution

  • Use a custom model binder:

    public class MyCustomBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext,
                                ModelBindingContext bindingContext)
        {
            HttpRequestBase request = controllerContext.HttpContext.Request;
    
            string day = request.Form.Get("DobDay");
            string month = request.Form.Get("DobMonth");
            string year = request.Form.Get("DobYear");
            //etc..
            return new Applicant
            {
                BirthDate = new DateTime(Convert.ToInt32(year), Convert.ToInt32(month), Convert.ToInt32(day))
                //etc..
            };
        }
    }
    
    [HttpPost]
    public ActionResult Save([ModelBinder(typeof(MyCustomBinder))] Applicant applicant)
    {
        return View();
    }