Web API - Как получить в контроллере DateTime ('dd/MM/yyyy') в качестве параметра Url?
Каждый раз, когда мой контроллер получает дату в виде дд / мм / гггг, он декодируется как MM / дд / гггг. Можно ли сказать контроллеру, как декодировать параметр URL?
Мой метод в контроллере:
[HttpGet]
public JsonResult<IList<Callers>> GetListOfCallers(DateTime startDate, DateTime endDate)
{
// myCode....
}
Мой JavaScript:
var $startDate = $('#startDate').val();
var $endDate = $('#endDate').val();
$.get(rootUrl + "api/report/GetListOfCallers?startDate=" + $startDate + "&endDate=" + $endDate, function (data) {
// myCode....
});
Я знаю, что могу получить дату в контроллере в виде строки и затем проанализировать ее или изменить ее в своем javascript на ISO8601, прежде чем вставлять URL-адрес, но я хочу знать, могу ли я сообщить своему контроллеру, как декодировать полученный параметр.
РЕДАКТИРОВАТЬ: Я использовал контроллер MVC, и это не было проблемой, он начал неправильно декодировать после того, как я перешел на ApiController, поэтому код работал, и я надеюсь сохранить как есть.
1 ответ
Мне удается решить мою проблему с помощью привязки модели, как это предложили @Jakotheshadows и @Amy.
Я использовал код из этого ответа о ModelBinders в Web Api с несколькими изменениями из этого ответа (он на португальском, но код понятен).
Итак, мой код прямо сейчас:
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?);
}
}
}
я использовал try
а также DateTime.Parse
как предлагается во второй ссылке, потому что первая всегда выдает исключение, даже с try и catch.
ModelBinderProvider я использовал, как он предложил:
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;
}
}
}
И я настраиваю как предложено здесь (также ответ для первой ссылки), но в моем WebApiConfig.cs
(не работал в Global.asax
), как это:
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 }
);
}
}
}
я думаю globalization
из Web.config
, uiCulture
а также culture
должен быть установлен на культуру, которую вы хотите, и enableClientBasedCulture
быть установленным как true
как здесь предлагается, но я не уверен, потому что я не хотел менять код, чтобы проверить его.