I have a search form with a DateTime search criterion, plus some other criteria:
<form method="get" action="/app/search">
<input type="text" value="13/01/2010" name="BeginDate"/>
<input type="text" value="blah" name="SomeOtherCriterion"/>
<form>
So I have a Search controller with a default Action (let's call it Index) and with a SearchCriteria parameter.
public class SearchController
{
public ActionResult Index(SearchCriteria searchCriteria) {//blah }
}
public class SearchCriteria
{
public DateTime BeginDate {get; set;}
public string SomeOtherCriterion {get; set;}
}
Now if I want to create an ActionLink, passing in a SearchCriteria value, thus:
Html.ActionLink("Search", "Index", searchCriteria)
I get the BeginDate query string parameter in US format. Looking on Google and poking around in System.Web.Routing using Reflector it seems to be because it uses the InvariantCulture, so there's nothing I can do about it.
It seems like noone has asked this question before so I guess I'm doing something very stupid.... Please help!
EDIT: Pass in SearchCriteria to ActionLink rather than anonymous object to show why I can't just do the custom ToString() myself.
Given that the framework appears to be hard-coded to handle this piece of data using InvariantCulture, I don't think there's much you can do to make it work transparently.
There is one ugly option - download the MVC source and rip out the code for all the offending classes from Route
down to ParsedRoute
to create your own RouteBase
implementation that does what you need.
If I absolutely had to keep the DateTime declaration on the SearchCriteria
class, then that's the route (sorry for the pun) I would choose.
However, a far easier solution would be to change your SearchCriteria class to use a slightly different declaration for the DateTime field, based on a type like this:
public class MyDateTime
{
public DateTime Value { get; set; }
//for passing MyDateTime in place of a DateTime without casting
public static implicit operator DateTime(MyDateTime instance) { return instance.Value; }
//so you can assign a MyDateTime from a DateTime without a cast
//- e.g. MyDateTime dt = DateTime.Now
public static implicit operator MyDateTime(DateTime instance) { return new MyDateTime() { Value = instance }; }
//override ToString so that CultureInfo.CurrentCulture is used correctly.
public override string ToString()
{
return Value.ToString(CultureInfo.CurrentUICulture);
}
}
In theory you should be able to roll out this change without too much fuss.
The big work could be if you have a lot of code that uses members (e.g. .Days etc) of the DateTime instance in SearchCriteria: you either have to reproduce those members on MyDateTime
, wrapping around the inner DateTime Value
or change all the code to use .Value.Member
.
To avoid issues related to Regional Settings and "Culture", I treat date and time as separate unbound fields and then assemble them into DateTime in my Controller.
Example:
Year [ ] Month [ ] Day [ ]
I always present separate textboxes for year, month, and day, in that order so that there can be no confusion between U.S. format (month/day/year) and more or less the rest of the world's format (day/month/year).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With