Aleksa
Aleksa

Reputation: 3104

Date binder culture

I have DateTime field in my model. The format in which I send date from frontend is d.m.Y H:i. And it is parsed ok.

But when I set US date format to be sent from frontend and set culture to en-US by typing Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US") in OnActionExecuting method which is run before my controller action it says that date is not valid at if (ModelState.IsValid).

My question is where in Asp.Net framework is set that default format is d.m.Y H:i and how can I change that default format? Does binder takes culture into consideration or it is always d.m.Y H:i?

Upvotes: 2

Views: 247

Answers (2)

Aleksa
Aleksa

Reputation: 3104

Thanks Vadim for your solution, but I found what is going on and solved it without custom date binder.

The problem is that parameter binding is done before the OnActionExecuting method where I put Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"), so the culture was still the default one when binding was done. And default culture is the one which is set in in Windows (system locale).

I changed it by putting <globalization culture="en-US"/> in <system.web> in Web.config.

So now binder parses US date correctly.

Upvotes: 1

Vadim Martynov
Vadim Martynov

Reputation: 8892

I solved the same issue with custom data binder that I added to my project.

First, I add new class DateTimeModelBinder:

public class DateTimeModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (value != null)
        {
            DateTime time;

            // here you can add your own logic to parse input value to DateTime
            //if (DateTime.TryParseExact(value.AttemptedValue, "d.m.Y H:i", CultureInfo.InvariantCulture, DateTimeStyles.None, out time))
            if (DateTime.TryParse(value.AttemptedValue, Culture.Ru, DateTimeStyles.None, out time))
            {
                return time;
            }
            else
            {
                bindingContext.ModelState.AddModelError(bindingContext.ModelName,
                    string.Format("Date {0} is not in the correct format", value.AttemptedValue));
            }
        }
        return base.BindModel(controllerContext, bindingContext);
    }
}

And then I add my bindeg in the Global.asax.cs on the application startup:

protected void Application_Start(object sender, EventArgs eventArgs)
{
    ModelBinders.Binders.Add(typeof(DateTime), new ateTimeModelBinder());
}

Upvotes: 1

Related Questions