I've been fighting with culture specific DateTime in ASP.NET MVC for few days now, to no avail. The scenario is as follows: I have a list which I want to filter against DateTime submitted by user. Users should handle dates in a localized form, in my case culture and cultureUI is set to "da-DK", so date format is "dd-mm-yy". So far I've managed to make the form submit date in the required format, but Action and ActionLink methods generate URLs that interpret dates in en-US ("mm/dd/yy").
Here's a sample project displaying the issue. The culture in Web.config is hardcoded to "da-DK":
<globalization culture="da-DK" uiCulture="da-DK" />
First the controller with two actions:
using System;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace DateTimeTest.Controllers
{
public class HomeController : Controller
{
public ViewResult Index(DateModel model)
{
return View(model);
}
public ViewResult Dummy(DateTime? date)
{
return View(date);
}
}
public class DateModel
{
[DataType(DataType.Date)]
public DateTime? Date { get; set; }
}
}
Index is an action displaying a form, where user can enter date in "dd-mm-yy" format. Form is posted to the same GET method (as I mentioned it's suppose to be filtering functionality), which will display the received date. Here's the Index.cshtml view:
@model DateTimeTest.Controllers.DateModel
<div>
@if (Model.Date != null)
{
<p>Received @Model.Date</p>
@Html.ActionLink("Dummy", "Dummy", new {Model.Date})
}
@using (Html.BeginForm("Index", "Home", FormMethod.Get))
{
@Html.EditorForModel()
}
</div>
To make this work, I had to use a custom model binder, processing the DateTime. A simplified version looks as follows:
using System;
using System.Web.Mvc;
namespace DateTimeTest.Infrastructure
{
public class DateTimeBinder: IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
string date = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue;
DateTime? result = DateTime.Parse(date);
return result;
}
}
}
This binder has been registered in Global.asax.cs with
ModelBinders.Binders.Add(typeof(DateTime?), new DateTimeBinder());
Now, when in the form I enter date "30-12-2013" and submit, Index view displays message "Received 30-12-2013 00:00:00" which is correct in my meaning. However the link to Dummy action looks like this:
http://localhost:53143/Home/Dummy?Date=12%2F30%2F2013%2000%3A00%3A00
which means the query string for Date is actually "12/30/2013 00:00:00". Clicking the link gives a FormatException in BindModel of the DateTimeBinder, because there are no 30 months in the calendar (it tries to process the date in da-DK format while what it gets is date in en-US). I know how to deal with exception itself but what I don't know is how to either force the system to use uniform DateTime format, or detect in the binder which format it comes in and act accordingly. I guess it boils down to question how URLs are generated by Html.Action and Html.ActionLink methods, though I might be wrong.
Note that I understand the need to treat GET URLs in en-US format (the post about fly tickets circulating around the web), though I would be willing to ignore this as the website I'm working on is an Intranet site where dates will only be used in da-DK format. Can anyone help me fix the issue? Thanks in advance.
PS. I'm using ASP.NET MVC 5.