MVC Date Time Model Binding
What I didn't see was where you registered your DateTimeModelBinder in your global.asax:
ModelBinders.Binders[typeof(DateTime)] =
new DateAndTimeModelBinder() { CustomFormat = "yyyy-mm-dd" };
Scott Hanselman has this very similar post working with DateTime Custom Model Binders
Mick Walker
Updated on April 26, 2020Comments
-
Mick Walker about 4 years
I am using 2 kendo date pickers in my application as such:
<div class="span12"> <div class="span2" style="text-align: right"> Start Date: </div> <div class="span2"> @(Html.Kendo().DatePickerFor(m=>m.StartDate)) </div> <div class="span2" style="text-align: right"> End Date: </div> <div class="span2"> @(Html.Kendo().DatePickerFor(m=>m.EndDate)) </div> <div class="span4"> <button class="btn btn-primary" onclick="getGraphData()">Show</button> </div> </div>
When the button is clicked, I read the values of these date pickers client side and make a POST to a API controller.
The issue I am having is sometimes the DateTime parameters are parsed incorrectly, I am using a en-GB culture (specified in my web.config), however given a date of 01/03/2014 (1st March), when the value is processed by the model binder, it is interpreted as 03/01/2014 (3rd Jan).
My javascript is as follows:
function getGraphData() { var startDatePicker = $("#StartDate").data("kendoDatePicker"); var endDatePicker = $("#EndDate").data("kendoDatePicker"); var param = { StartDate: kendo.toString(startDatePicker.value().toLocaleDateString(), "dd/MM/yyyy"), EndDate: kendo.toString(endDatePicker.value().toLocaleDateString(), "dd/MM/yyyy") }; // Do post here }
My model is as follows:
public class DateRangeParam { #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="DateRangeParam"/> class. /// </summary> public DateRangeParam() { this.EndDate = DateTime.Today.AddDays(1).AddSeconds(-1); this.StartDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1); } #endregion #region Public Properties /// <summary> /// Gets or sets the end date. /// </summary> public DateTime EndDate { get; set; } /// <summary> /// Gets or sets the start date. /// </summary> public DateTime StartDate { get; set; } #endregion }
I figured the solutions was that I needed a custom model binder to parse the datetime value, so I created on (as follows) and registered it in the Global.asax.cs file, but this didnt work, the binder is never called, I am unsure if this is because the datetime is a property of a custom object.
public class DateTimeModelBinder : IModelBinder { #region Fields private readonly string _customFormat; #endregion #region Constructors and Destructors public DateTimeModelBinder(string customFormat) { this._customFormat = customFormat; } #endregion #region Explicit Interface Methods object IModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { ValueProviderResult value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); return DateTime.ParseExact(value.AttemptedValue, this._customFormat, CultureInfo.InvariantCulture); } #endregion }
And it is registered as follows:
var binder = new DateTimeModelBinder(new CultureInfo("en-GB").DateTimeFormat.ShortDatePattern); ModelBinders.Binders.Add(typeof(DateTime), binder); ModelBinders.Binders.Add(typeof(DateTime?), binder);
Does anyone know where I am going wrong?
-
sarin about 10 yearsWell known behaviour. [See this stack overflow post][1] [or this one][2] [1]: stackoverflow.com/questions/15147467/… [2]: stackoverflow.com/questions/4349589/…
-
Mick Walker about 10 yearsWhile I understand that this is a well known issue, I am unsure of why my custom binder is not even called.
-
-
Mick Walker about 10 yearsThanks for this, what I eventually did was post the parameter to the controller as a UTC timestamp, and boom, MVC automatically converts the timestamp to a valid date time so my model binds nicely :)