I manage to solve my problem using Model binding as suggested by @Jakotheshadows and @Amy.
I used the code from this answer about ModelBinders in Web Api with a few tweaks from this answer (it's in portuguese, but the code is clear).
So my code right now:
using System;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
namespace Site.Services
{
public class DateTimeModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
ValidateBindingContext(bindingContext);
if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName) ||
!CanBindType(bindingContext.ModelType))
{
return false;
}
var modelName = bindingContext.ModelName;
var attemptedValue = bindingContext.ValueProvider
.GetValue(modelName).AttemptedValue;
try
{
bindingContext.Model = DateTime.Parse(attemptedValue);
}
catch (FormatException e)
{
bindingContext.ModelState.AddModelError(modelName, e);
}
return true;
}
private static void ValidateBindingContext(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException("bindingContext");
}
if (bindingContext.ModelMetadata == null)
{
throw new ArgumentException("ModelMetadata cannot be null", "bindingContext");
}
}
public static bool CanBindType(Type modelType)
{
return modelType == typeof(DateTime) || modelType == typeof(DateTime?);
}
}
}
I used try and DateTime.Parse as suggested in the second link, because the first always throwed an exception even with try and catch.
The ModelBinderProvider I used as he suggested:
using System;
using System.Web.Http;
using System.Web.Http.ModelBinding;
namespace Site.Services
{
public class DateTimeModelBinderProvider : ModelBinderProvider
{
readonly DateTimeModelBinder binder = new DateTimeModelBinder();
public override IModelBinder GetBinder(HttpConfiguration configuration, Type modelType)
{
if (DateTimeModelBinder.CanBindType(modelType))
{
return binder;
}
return null;
}
}
}
And I configure as suggested here (also an answer for the first link), but in my WebApiConfig.cs (didn't work in Global.asax), like this:
using Site.Services;
using System;
using System.Web.Http;
namespace Site
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.BindParameter(typeof(DateTime), new DateTimeModelBinder());
config.BindParameter(typeof(DateTime?), new DateTimeModelBinder());
//Rest of my code
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
I think the globalization of the Web.config, the uiCulture and culture must be set to the culture you want and enableClientBasedCulture be set as true as suggest here, but I'm not sure because I didn't want to change the code to test it.