I have a controller POST action that redirects to a GET method using RedirectToAction.
return RedirectToAction(SomeActionName, new { date = someModel.someUTCDate });
I have implemented a custom model binder which parses dates using the assumed culture and timezone information, so I am intercepting this correctly. The basic steps in my problem:
- POST action is called with a date/time string, which is GMT Standard Time if not specified otherwise
- The custom model binder parses this date to a DateTime with a Kind of Utc, and this is bound correctly in the correct format to the model
- The POST action redirects to GET using RedirectToAction with the date that was bound as UTC time on the model
- MVC3 is now trying to bind a DateTime string value with the month and day swapped around
Somewhere between calling RedirectToAction and rebinding the DateTime value for the GET action, a string conversion is taking place, which appears to be swapping the month and the day around.
Is there a simple way of ensuring that the correct string conversion takes place without the overhead of having to manually convert it for each RedirectToAction call? I would really like to know where this route value to string conversion takes place and whether or not I could influence it to do the correct string conversion.
To illustrate what I have a bit better, I have a custom DateTime model binder
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ValueProviderResult value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (value == null || string.IsNullOrEmpty(value.AttemptedValue) || value.AttemptedValue == "null")
{
return null;
}
return FormatHelper.ConvertStringFromGMT(value.AttemptedValue);
}
On redirect I am finding that the model binder’s value.AttemptedValue is an incorrectly formatted string.
Well, the issue is now resolved. As far as I can tell, when MVC gets the route values for your redirect, the route values are converted to query string parameters using the invariant culture. This is just some magic that happens behind the scenes. My solution to this problem was to override the controller methods RedirectToAction and RedirectToActionPermanent (the overloads that take a RouteValueDictionary). I iterate over the RouteValueDictionary and convert any date types here using the defined culture and timezone information. Fortunately all of my controllers were already inheriting from a custom base controller so the fix was simple to implement.