Everytime my controller receives a date as dd/MM/yyyy it decode as MM/dd/yyyy. Is it possible to tell the controller how to decode the parameter of the url?
My method in controller:
[HttpGet]
public JsonResult<IList<Callers>> GetListOfCallers(DateTime startDate, DateTime endDate)
{
// myCode....
}
My javascript:
var $startDate = $('#startDate').val();
var $endDate = $('#endDate').val();
$.get(rootUrl + "api/report/GetListOfCallers?startDate=" + $startDate + "&endDate=" + $endDate, function (data) {
// myCode....
});
I know I can receive the date in controller as string and then parse it, or change it in my javascript to ISO8601 before putting in the url, but I want to know if I can tell my controller how to decode the parameter received.
EDIT: I was using MVC controller and this was not a problem, it started decoding incorrectly after I changed to ApiController, so the code was working and I hope to keep as it is.
-
I believe you need to convert it from string to date, and in the process of decoding the string to a date, you can customize that however you want.C. Helling– C. Helling2017年09月06日 20:01:39 +00:00Commented Sep 6, 2017 at 20:01
-
1Model binding is your friend, here is what my googling on the subject related to your question revealed: vickram.me/custom-datetime-model-binding-in-asp-net-web-apiJakotheshadows– Jakotheshadows2017年09月06日 20:05:35 +00:00Commented Sep 6, 2017 at 20:05
-
I agree, custom model binding is the way to go here.user47589– user475892017年09月06日 20:08:06 +00:00Commented Sep 6, 2017 at 20:08
-
@Jakotheshadows Model binding works for url as well? I thought it was only for post methods.GTPON– GTPON2017年09月06日 20:14:26 +00:00Commented Sep 6, 2017 at 20:14
-
1@Robert I don't think it changes, but it's a solution I don't want to use. I want a solution to implement in all projects so others programmers don't have to worry about conversions.GTPON– GTPON2017年09月08日 16:14:15 +00:00Commented Sep 8, 2017 at 16:14
1 Answer 1
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.
Comments
Explore related questions
See similar questions with these tags.