IAmGroot
IAmGroot

Reputation: 13855

ASP.NET MVC3: Force controller to use date format dd/mm/yyyy

Basically, my datepicker uses UK format of dd/mm/yyyy. But when I submit the form, ASP.net is clearly using US format. (will only accept days if less than 12, i.e. thinks it is the month.)

 public ActionResult TimeTable(DateTime ViewDate)

Is there a way to force it to recognise a certain way?

Strangely though, other methods of insert seem to recognise the correct format.

"The parameters dictionary contains a null entry for parameter ViewDate of non-nullable type System.DateTime for method System.Web.Mvc.ActionResult Index(System.DateTime) in Mysite.Controllers.RoomBookingsController. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."

Upvotes: 13

Views: 14768

Answers (6)

TomTom
TomTom

Reputation: 62093

Basically, my datepicker uses UK format of dd/mm/yyyy

Beginner mistake. It should use whatever format the browser is set to. The problem is not a format, but different formats between client and server. The server should emit code that formats the date according to the negotiated locale which the server then also uses to parse it.

But when I submit the form, ASP.NET is clearly using US format.

Nope. This is saying that when I take a spice it always is salt and then you always take salt. Your Server accepts the currently negotiated culture which - unless you modify settings - is negotiated between client and server. Check the threads current culture when it should do the parsing to see what it is set for.

Upvotes: 2

Gumowy Kaczak
Gumowy Kaczak

Reputation: 1499

From my BindigTools for bindning DateTime? (Nullable), based on some book sample - Pro MVC3

    public static DateTime? GetValueNDateTime(ModelBindingContext context, string searchPrefix, string key, string format)
    {
        ValueProviderResult vpr = context.ValueProvider.GetValue(searchPrefix + key);
        DateTime outVal;
        if (DateTime.TryParseExact(vpr.AttemptedValue, format, null, System.Globalization.DateTimeStyles.None, out outVal))
        {
            return outVal;
        }
        else
        {
            return null;
        }
    }

It uses parsing exact so you shouldn't have any problem with parsed dates.

Upvotes: 0

Gumowy Kaczak
Gumowy Kaczak

Reputation: 1499

You can do it:

  • globally (in global.asax under Application_Start() ):

    ModelBinders.Binders.Add(typeof(DateTime), new DateTimeModelBinder()); 
    
  • for a method:

        public ActionResult TimeTable([Binder(typeof(DateTimeModelBinder)]DateTime ViewDate)
    
  • for a custom model class - ah no, no posibility cause you use struct DateTime ;-)

Ah, sorry I couldn't add a comment to Adams post - it's based on his code.

Upvotes: 2

Adam Flanagan
Adam Flanagan

Reputation: 3052

Have a read of this. It gives a good explanation of what's happening and why it works as it does.

I'm in the situation where I know everyone using the site is in the UK so I can safely override the default DateTime model binder:

public class DateTimeModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var date = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue;

        if (String.IsNullOrEmpty(date))
            return null;

        bindingContext.ModelState.SetModelValue(bindingContext.ModelName, bindingContext.ValueProvider.GetValue(bindingContext.ModelName));
        try
        {
            return DateTime.Parse(date);
        }
        catch (Exception)
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, String.Format("\"{0}\" is invalid.", bindingContext.ModelName));
            return null;
        }
    }
}

Upvotes: 17

Sebastian Piu
Sebastian Piu

Reputation: 8008

Have you tried setting the Current Culture as en-GB?

protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
     base.Initialize(requestContext);

     CultureInfo cultureInfo = CultureInfo.GetCultureInfo("en-GB");

     Thread.CurrentThread.CurrentCulture = cultureInfo;
     Thread.CurrentThread.CurrentUICulture = cultureInfo;                    
 }

Upvotes: 2

Gumowy Kaczak
Gumowy Kaczak

Reputation: 1499

You need to use custom ModelBinder for your DateTime. I had that same problem as you.

Upvotes: 3

Related Questions