Web API - 如何在控制器中接收 DateTime ('dd/MM/yyyy') 作为 Url 参数?

Posted

技术标签:

【中文标题】Web API - 如何在控制器中接收 DateTime (\'dd/MM/yyyy\') 作为 Url 参数?【英文标题】:Web API - How to receive in controller DateTime ('dd/MM/yyyy') as Url parameter?Web API - 如何在控制器中接收 DateTime ('dd/MM/yyyy') 作为 Url 参数? 【发布时间】:2018-02-15 10:12:09 【问题描述】:

每次我的控制器收到日期为 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 后它开始解码错误,所以代码可以正常工作,我希望保持原样。

【问题讨论】:

我相信您需要将其从字符串转换为日期,并且在将字符串解码为日期的过程中,您可以随意自定义。 模型绑定是你的朋友,这是我在谷歌上搜索与你的问题相关的内容:vickram.me/custom-datetime-model-binding-in-asp-net-web-api 我同意,自定义模型绑定是要走的路。 @Jakotheshadows 模型绑定也适用于 url?我以为它只适用于 post 方法。 @Robert 我不认为它会改变,但这是我不想使用的解决方案。我想要一个在所有项目中实施的解决方案,这样其他程序员就不必担心转换。 【参考方案1】:

按照@Jakotheshadows 和@Amy 的建议,我设法使用模型绑定解决了我的问题。

我使用了this answer 中关于 Web Api 中的 ModelBinders 的代码,并对 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.config 中的globalizationuiCultureculture 必须设置为您想要的文化,enableClientBasedCulture 设置为true 建议here,但我'我不确定,因为我不想更改代码来测试它。

【讨论】:

以上是关于Web API - 如何在控制器中接收 DateTime ('dd/MM/yyyy') 作为 Url 参数?的主要内容,如果未能解决你的问题,请参考以下文章

C# Web 服务,如何接收 JSON

在 ASP.NET Core Web API 中上传文件和 JSON

以 axios.post 形式接收 asp.net core web api 中的数组

Asp.Net MVC 中 Web API 的默认控制器操作

Web Api 控制器和线程池

当 HttpClient 超时时,Web API 控制器中的请求会发生啥?