Web API - 如何在控制器中接收 DateTime ('dd/MM/yyyy') 作为 Url 参数?
Web API - How to receive in controller DateTime ('dd/MM/yyyy') as Url parameter?
每次我的控制器收到 dd/MM/yyyy 的日期时,它都会解码为 MM/dd/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....
});
我知道我可以在控制器中接收日期作为字符串然后解析它,或者在放入 url 之前将我的 javascript 中的日期更改为 ISO8601,但我想知道我是否可以告诉我的控制器如何解码收到的参数。
编辑:我使用的是 MVC 控制器,这不是问题,在我更改为 ApiController 后它开始解码不正确,所以代码可以正常工作,我希望保持原样是的。
我按照@Jakotheshadows 和@Amy 的建议使用模型绑定设法解决了我的问题。
我使用了 this answer about ModelBinders in Web Api with a few tweaks from 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?);
}
}
}
我按照第二个 link 中的建议使用 try
和 DateTime.Parse
,因为第一个总是抛出异常,即使使用 try and 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(也是第一个 link 的答案),但在我的 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,但我不确定,因为我不想更改代码来测试它。
每次我的控制器收到 dd/MM/yyyy 的日期时,它都会解码为 MM/dd/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....
});
我知道我可以在控制器中接收日期作为字符串然后解析它,或者在放入 url 之前将我的 javascript 中的日期更改为 ISO8601,但我想知道我是否可以告诉我的控制器如何解码收到的参数。
编辑:我使用的是 MVC 控制器,这不是问题,在我更改为 ApiController 后它开始解码不正确,所以代码可以正常工作,我希望保持原样是的。
我按照@Jakotheshadows 和@Amy 的建议使用模型绑定设法解决了我的问题。
我使用了 this answer about ModelBinders in Web Api with a few tweaks from 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?);
}
}
}
我按照第二个 link 中的建议使用 try
和 DateTime.Parse
,因为第一个总是抛出异常,即使使用 try and 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(也是第一个 link 的答案),但在我的 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,但我不确定,因为我不想更改代码来测试它。