ASP.NET MVC datetime culture issue when passing value back to controller

Jim Wolff picture Jim Wolff · Oct 25, 2011 · Viewed 26.4k times · Source

How can i tell my controller/model what kind of culture it should expect for parsing a datetime?

I was using some of this post to implement jquery datepicker into my mvc application.

When i submit the date it gets "lost in translation" i'm not using the US formatting for the date, so when it gets sent to my controller it simply becomes null.

I have a form where the user chooses a date:

@using (Html.BeginForm("List", "Meter", FormMethod.Get))
{
    @Html.LabelFor(m => m.StartDate, "From:")
    <div>@Html.EditorFor(m => m.StartDate)</div>

    @Html.LabelFor(m => m.EndDate, "To:")
    <div>@Html.EditorFor(m => m.EndDate)</div>
}

I've made an edit template for this, to implement the jquery datepicker:

@model DateTime
@Html.TextBox("", Model.ToString("dd-MM-yyyy"), new { @class = "date" }) 

I then create the datepicker widgets like this.

$(document).ready(function () {
    $('.date').datepicker({ dateFormat: "dd-mm-yy" });
});

All this works fine.

Here is where the problems start, this is my controller:

[HttpGet]
public ActionResult List(DateTime? startDate = null, DateTime? endDate = null)
{
    //This is where startDate and endDate becomes null if the dates dont have the expected formatting.
}

This is why i would like to somehow tell my controller what culture it should expect? Is my model wrong? can i somehow tell it which culture to use, like with the data annotation attributes?

public class MeterViewModel {
    [Required]
    public DateTime StartDate { get; set; }
    [Required]
    public DateTime EndDate { get; set; }
}

Edit: this link explains my issue and a very good solution to it aswell. Thanks to gdoron

Answer

you can change the default model binder to use the user culture using IModelBinder

   public class DateTimeBinder : IModelBinder
   {
       public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
       {
           var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
           var date = value.ConvertTo(typeof(DateTime), CultureInfo.CurrentCulture);

           return date;    
       }
   }

And in the Global.Asax write:

ModelBinders.Binders.Add(typeof(DateTime), new DateTimeBinder());
ModelBinders.Binders.Add(typeof(DateTime?), new DateTimeBinder());

Read more at this excellent blog that describe why Mvc framework team implemented a default Culture to all users.