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