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解码错误,因此代码在工作,我希望能保持原样。

+0

我相信你需要将它从字符串转换为日期,并且在将字符串解码为一个日期的过程中,你可以自定义你想要的。 –

+1

模型绑定是你的朋友,这里是我的谷歌搜索与你的问题相关的主题显示: http://www.vickram.me/custom-datetime-model-binding-in-asp-net-web-api/ – Jakotheshadows

+0

我同意,自定义模型绑定是去这里的方式。 – Amy

我使用@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?); 
     } 
    } 
} 

我用tryDateTime.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.configglobalizationuiCultureculture必须设置为你想要的文化和enableClientBasedCulture被设置为true建议here,但我不确定,因为我不想更改代码来测试它。