使用ASP.NET Web API将表单yyyy-MM-dd的日期查询参数反序列化为noda time LocalDate对象

我正在调查使用NodaTime LocalDate来替换我们现有的BCL DateTime / DateTimeOffset类的使用。 由于我们对DateTime可论证的模糊行为的误解,我们在代码中遇到了许多与时区相关的问题。

为了充分利用NodaTime,我希望能够从YYYY-MM-DDforms的ASP.NET Web API 2 Web服务发送和接收日期。 我已成功将LocalDate正确序列化为YYYY-MM-DD。 但是,我无法将日期查询参数反序列化为LocalDate。 LocateDate始终是1970-01-01。

这是我当前的原型代码(为清晰起见,删除了一些代码):

PeopleController.cs

[RoutePrefix("api")] public class PeopleController : ApiController { [Route("people")] public LocalDate GetPeopleByBirthday([FromUri]LocalDate birthday) { return birthday; } } 

的Global.asax.cs

 public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { // Web API configuration and services var formatters = GlobalConfiguration.Configuration.Formatters; var jsonFormatter = formatters.JsonFormatter; var settings = jsonFormatter.SerializerSettings; settings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); settings.Formatting = Formatting.Indented; settings.ContractResolver = new CamelCasePropertyNamesContractResolver(); GlobalConfiguration.Configure(WebApiConfig.Register); } } 

我通过执行Web服务

 http://localhost/api/people?birthday=1980-11-20 

但是,返回的是1970年1月1日。进入代码我确认birthday设置为1970-01-01。

如何配置序列化,以便将URL中指定的日期作为查询参数(或路径元素)正确序列化为NodaTime LocalDate?

感谢Microsoft提供的这篇非常有用的文章 ,我能够使用自定义模型绑定器找到解决方案。

将此类添加到项目中:

 public class LocalDateModelBinder : IModelBinder { private readonly LocalDatePattern _localDatePattern = LocalDatePattern.IsoPattern; public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { if (bindingContext.ModelType != typeof (LocalDate)) return false; var val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (val == null) return false; var rawValue = val.RawValue as string; var result = _localDatePattern.Parse(rawValue); if (result.Success) bindingContext.Model = result.Value; return result.Success; } } 

然后更改您的控制器方法以使用它。

 public LocalDate GetPeopleByBirthday( [ModelBinder(typeof(LocalDateModelBinder))] LocalDate birthday) 

文章还提到了注册模型绑定器的其他方法。

请注意,由于您的方法返回一个LocalDate ,您仍然需要Json.net的Noda Time serialziation,因为它最终会在正文中用于返回值。