Web API - 如何在控制器中接收DateTime('dd/MM/yyyy')作为Url参数?
问题描述:
每当我的控制器收到一个日期为dd/MM/yyyy时,它会解码为MM/dd/yyyy。是否有可能告诉控制器如何解码url的参数?Web API - 如何在控制器中接收DateTime('dd/MM/yyyy')作为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解码错误,因此代码在工作,我希望能保持原样。
答
我使用@Jakotheshadows和@Amy建议的模型绑定解决了我的问题。
我使用了this answer关于ModelBinders在Web Api中的代码,并从this answer(这是用葡萄牙语,但代码很清楚)进行了一些调整。
所以我的代码现在:
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;
}
}
}
我配置为建议here(也是第一个链接的答案),但在我的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 }
);
}
}
}
我觉得Web.config
的globalization
的uiCulture
和culture
必须设置为你想要的文化和enableClientBasedCulture
被设置为true
建议here,但我不确定,因为我不想更改代码来测试它。
我相信你需要将它从字符串转换为日期,并且在将字符串解码为一个日期的过程中,你可以自定义你想要的。 –
模型绑定是你的朋友,这里是我的谷歌搜索与你的问题相关的主题显示: http://www.vickram.me/custom-datetime-model-binding-in-asp-net-web-api/ – Jakotheshadows
我同意,自定义模型绑定是去这里的方式。 – Amy