So I have a custom Model Binder implemented for DateTime
type and I register it like below:
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
GlobalConfiguration.Configuration.BindParameter(typeof(DateTime), new CurrentCultureDateTimeAPI());
}
and then I have setup 2 sample actions to see if my custom model binding takes place:
[HttpGet]
public void BindDateTime([FromUri]DateTime datetime)
{
//http://localhost:26171/web/api/BindDateTime?datetime=09/12/2014
}
[HttpGet]
public void BindModel([FromUri]User user)
{
//http://localhost:26171/web/api/BindModel?Name=ibrahim&JoinDate=09/12/2014
}
When I run and invoke both actions from mentioned URLs, user
's JoinDate
property successfully gets bound using the custom binder I configured but BindDateTime
's datetime
parameter does not get bound using the custom binder.
I have already specified in config that all DateTime
should use my custom binder then why the indifference? Suggestions are highly appreciated.
CurrentCultureDateTimeAPI.cs:
public class CurrentCultureDateTimeAPI: IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
var date = value.ConvertTo(typeof(DateTime), CultureInfo.CurrentCulture);
bindingContext.Model = date;
return true;
}
}
NOTE: If I use [FromUri(Binder=typeof(CurrentCultureDateTimeAPI))]DateTime datetime
then it works as expected but then again why?
To force Web API to read a complex type from the URI, add the [FromUri] attribute to the parameter. The following example defines a GeoPoint type, along with a controller method that gets the GeoPoint from the URI.
Use [FromUri] attribute to force Web API to get the value of complex type from the query string and [FromBody] attribute to get the value of primitive type from the request body, opposite to the default rules.
Pretty surprising too :)
My initial doubt was this line:
GlobalConfiguration.Configuration.BindParameter(typeof(DateTime), new CurrentCultureDateTimeAPI());
MSDN says GlobalConfiguration
=> GlobalConfiguration provides a global System.Web.HTTP.HttpConfiguration for ASP.NET application
.
But for weird reasons this does not seem to work with this particular scenario.
So,
Just add this line inside the static class WebApiConfig
config.BindParameter(typeof(DateTime), new CurrentCultureDateTimeAPI());
so that your WebAPIConfig
file looks like:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "web/{controller}/{action}/{datetime}",
defaults: new { controller = "API", datetime = RouteParameter.Optional }
);
config.BindParameter(typeof(DateTime), new CurrentCultureDateTimeAPI());
}
And everything works fine because this method is directly invoked by WebAPI framework
so for sure your CurrentCultureDateTimeAPI
gets registered.
Checked this with your solution and works great.
Note: (From the comments) You can still support Attribute Routing
and you need not comment out this line config.MapHttpAttributeRoutes()
.
But still, It would be great if somebody can tell why GlobalConfiguration
does not work out
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