MorgoZ
MorgoZ

Reputation: 2052

DateTime.Parse not working on an MVC custom binder

I'm getting a DateTime from an implicit binding at an Action in a .NET MVC web application. The problem is that i'm getting the date in format "MM/dd/yyyy" while i'm sending it through a query string with Ajax in format "dd/MM/yyyy".

I know this is a known issue of the .NET MVC Binder when using the GET protocol and not POST, so i did implement a custom binder to parse the date to the correct format. Here is the code:

public class SearchVMBinder:DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        SearchVM result = (SearchVM)base.BindModel(controllerContext, bindingContext);
        try
        {                
            result.Date = DateTime.Parse(result.Date.ToString(),CultureInfo.GetCultureInfo("es-ES"));
        }
        catch(Exception e)
        {
            NLog.LogManager.GetCurrentClassLogger().Error("Error al hacer el Bind específico de SearchVM. ", e);
        }

        return result;
    }
}

But, with that code the Parse is not working, it just does nothing. I'm testing it with a date like "01/04/2014 11:37:00" (april) and i'm getting at the "result.Date" the date "04/01/2014 11:37:00" (january), before and afert parsing.

So, the question is: Why is the method "DateTime.Parse" not parsing the date correctly?

UPDATE:

Here is the code of the SearchVM:

[ModelBinder(typeof(SearchVMBinder))]
public class SearchVM
{
    public DateTime Date { get; set; }
    public string StudyCaseNumber { get; set; }
    public string PatientNumber { get; set; }
    public string PatientName { get; set; }
    public string PatientFamilyName { get; set; }
    public string PatientMothersMaidenName { get; set; }
    public string DoctorName { get; set; }
    public string RoomName { get; set; }
    public E_OrderedBy OrderBy { get; set; }

}

and here the header of the controller's action:

public ActionResult ListSearch(SearchVM searchFilter)

Thank you.

Upvotes: 0

Views: 587

Answers (4)

MorgoZ
MorgoZ

Reputation: 2052

Ok, for some reason the "Parse" method did not interpret properly the incoming DateTime format, which was "MM/dd/yyyy H:mm:ss", so i had to use the "ParseExact" method to specify it.

Now, this works perfect for a spanish culture info:

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        SearchVM result = (SearchVM)base.BindModel(controllerContext, bindingContext);
        try
        {
            if (result != null)
            {
                if (result.NullableDate != null)
                {                                      
                    result.NullableDate = DateTime.ParseExact(result.NullableDate.ToString(), "MM'/'dd'/'yyyy H:mm:ss", new CultureInfo("es-ES"));
                }
            }

        }
        catch(Exception e)
        {
            NLog.LogManager.GetCurrentClassLogger().Error("Error al hacer el Bind específico de SearchVM. ", e);
        }

        return result;
    }

Upvotes: 0

tacos_tacos_tacos
tacos_tacos_tacos

Reputation: 10575

Your code is working.

See the top answer on this question: Convert DateTime from English to Spanish

You said:

But, with that code the Parse is not working, it just does nothing. I'm testing it with a date like "01/04/2014 11:37:00" (april) and i'm getting at the "result.Date" the date "04/01/2014 11:37:00" (january), before and afert parsing.

That's quite a specific kind of not working - the kind that is the result of a difference in locale. You have used "es-ES" format.

https://www.bjelic.net/2011/01/26/coding/formatting-date-time-currency-in-various-cultures/

result.Date = 

    DateTime.Parse(result.Date.ToString(),
    CultureInfo.GetCultureInfo("es-ES"));

The resultant date is according to you "01/04/2014 11:37:00" and the es-ES locale is dd/MM/yyyy, so since you are currently using english it does the conversion.

Upvotes: 0

Husni Salax
Husni Salax

Reputation: 2020

Here we go:

Try to post/send your DateTime as UTC string: You may convert like this:

DateTime startdate = TimeZoneInfo.ConvertTimeToUtc(input.startdate.Value);   //Converting to UTC time from local time

Hope it helps;)

Upvotes: 0

Amin K
Amin K

Reputation: 106

something like this would work

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var testFormat = bindingContext.ModelMetadata.DisplayFormatString;
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        if (!string.IsNullOrEmpty(testFormat) && value != null)
        {
            DateTime testDate;
            testFormat = testFormat.Replace("{0:", string.Empty).Replace("}", string.Empty);
            // use the format specified in the testFormat attribute to parse the date
            if(DateTime.TryParseExact(value.AttemptedValue, testFormat, new System.Globalization.CultureInfo("es-ES"), DateTimeStyles.None, out testDate);)
            {
                return testDate;
            }
            else
            {
                //if you want allow nulls
                //date = DateTime.Now.Date;
                //return date;

                bindingContext.ModelState.AddModelError(
                    bindingContext.ModelName,
                    string.Format("{0} is an invalid date format", value.AttemptedValue)
                );
            }
        }

        return base.BindModel(controllerContext, bindingContext);
    }

Upvotes: 0

Related Questions