MVC Date Time Model Binding

21,215

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

Share:
21,215
Mick Walker
Author by

Mick Walker

Updated on April 26, 2020

Comments

  • Mick Walker
    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?

  • Mick Walker
    Mick Walker about 10 years
    Thanks 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 :)