【问题标题】:Asp.Net Web Api - posting UK date formatsAsp.Net Web Api - 发布英国日期格式
【发布时间】:2012-08-30 11:11:46
【问题描述】:

我希望我的用户能够以英国格式将日期发布到 asp.net Web api 控制器,例如 01/12/2012(2012 年 12 月 1 日)。

据我所知,默认情况下,只接受 us 格式。

我可以在某处更改某些内容以使英国格式成为默认格式吗?我尝试更改 web.config 中的全球化设置,但这没有效果。

保罗

【问题讨论】:

  • 您可能还需要更改 jquery-validation 代码以包含英国本地化版本。 (我假设你正在使用 MVC)
  • 服务器是否设置为英国日期时间设置?
  • 我的本地验证工作正常,问题是发布到 api 控制器,除非在我的 DateTime 属性为空时它是我们的格式。
  • 是的,这是我的开发机器,全英国
  • 在下面查看我的答案:

标签: asp.net asp.net-web-api date-format


【解决方案1】:

使用自定义模型绑定器完成此操作,这与 MVC3 中的模型绑定器略有不同:

public class DateTimeModelBinder : IModelBinder
    {

        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
            var date = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue;

            if (String.IsNullOrEmpty(date))
                return false;

            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, bindingContext.ValueProvider.GetValue(bindingContext.ModelName));
            try
            {
                bindingContext.Model = DateTime.Parse(date);
                return true;
            }
            catch (Exception)
            {
                bindingContext.ModelState.AddModelError(bindingContext.ModelName, String.Format("\"{0}\" is invalid.", bindingContext.ModelName));
                return false;
            }
        }
    }

在我的 Global.asax.cs 文件中,添加这一行以告诉 api 将此模型绑定器用于 DateTime 值:

GlobalConfiguration.Configuration.BindParameter(typeof(DateTime), new DateTimeModelBinder());

这是我的 api 控制器中的方法:

public IList<LeadsLeadRowViewModel> Get([ModelBinder]LeadsIndexViewModel inputModel)

我的 LeadsIndexViewModel 类有几个 DateTime 属性,这些属性现在都是有效的英国日期时间。

【讨论】:

  • 顺便说一句,这仅适用于获取请求...仍在寻找发布请求的解决方案。
  • 你找到POST request的解决方案了吗?
【解决方案2】:

嗯,我也想在全球范围内解决这个问题......并在此过程中扯掉了很多头发。事实证明,WebApi 中没有扩展点,人们希望拦截传入的表单数据并根据需要对其进行修改。那不是很好吗。因此,缺少这些,我尽可能深入地研究 WebApi 源代码,看看我能想出什么。我最终重用了负责解析表单数据的类来创建模型。我只添加了几行来专门处理日期。下面的那个类可以像这样添加到配置中:

  private static void PlaceFormatterThatConvertsAllDatesToIsoFormat(HttpConfiguration config)
  {
             config.Formatters.Remove(
                 config.Formatters.FirstOrDefault(x => x is JQueryMvcFormUrlEncodedFormatter));

             config.Formatters.Add(
                 new IsoDatesJQueryMvcFormUrlEncodedFormatter());
}

格式化程序:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Threading.Tasks;
using System.Web.Http.ModelBinding;

namespace WebApi.Should.Allow.You.To.Set.The.Binder.Culture
{
    // This class replaces WebApi's JQueryMvcFormUrlEncodedFormatter 
    // to support JQuery schema on FormURL. The reasong for this is that the 
    // supplied class was unreliable when parsing dates european style.
    // So this is a painful workaround ...
    /// <remarks>
    /// Using this formatter any string that can be parsed as a date will be formatted using ISO format
    /// </remarks>
    public class IsoDatesJQueryMvcFormUrlEncodedFormatter : FormUrlEncodedMediaTypeFormatter
    {

        // we *are* in Israel
        private static readonly CultureInfo israeliCulture = new CultureInfo("he-IL");

        public override bool CanReadType(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            return true;
        }

        public override Task<object> ReadFromStreamAsync(Type type
            , Stream readStream
            , HttpContent content
            , IFormatterLogger formatterLogger)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (readStream == null)
            {
                throw new ArgumentNullException("readStream");
            }

            // For simple types, defer to base class
            if (base.CanReadType(type))
            {
                return base.ReadFromStreamAsync(type, readStream, content, formatterLogger);
            }

            var result = base.ReadFromStreamAsync(
                                typeof(FormDataCollection), 
                                readStream, 
                                content, 
                                formatterLogger);

            Func<object, object> cultureSafeTask = (state) =>
            {
                var innterTask = (Task<object>)state;
                var formDataCollection = (FormDataCollection)innterTask.Result;
                var modifiedCollection = new List<KeyValuePair<string, string>>();

                foreach (var item in formDataCollection)
                {
                    DateTime date;
                    var isDate =
                        DateTime.TryParse(item.Value,
                                            israeliCulture,
                                            DateTimeStyles.AllowWhiteSpaces,
                                            out date);

                    if (true == isDate)
                    {
                        modifiedCollection.Add(
                            new KeyValuePair<string, string>(
                                item.Key,
                                date.ToString("o")));
                    }
                    else
                    {
                        modifiedCollection.Add(
                            new KeyValuePair<string, string>(
                                item.Key,
                                item.Value));
                    }
                }

                formDataCollection = new FormDataCollection(modifiedCollection);

                try
                {
                    return
                        formDataCollection.ReadAs(type, String.Empty, RequiredMemberSelector, formatterLogger);
                }
                catch (Exception e)
                {
                    if (formatterLogger == null)
                    {
                        throw;
                    }

                    formatterLogger.LogError(String.Empty, e);

                    return GetDefaultValueForType(type);
                }
            };

            return
                Task.Factory.StartNew(
                cultureSafeTask
                            , result);
        }
    }
} 

【讨论】:

    【解决方案3】:

    这里有一个将 jQuery 日期选择器本地化为 en-gb 的示例:http://weblogs.asp.net/hajan/archive/2010/10/05/integration-of-jquery-datepicker-in-asp-net-website-localization-part-3.aspx

    另外,我看到您尝试将文化设置为 en-GB,但我不知道您是否尝试在 Web.Config 中设置 UI 文化(而且我不知道这是否会影响 jQuery 捆绑包MVC 与否):

    <globalization requestEncoding="utf-8" responseEncoding="utf-8" culture="en-GB" uiCulture="en-GB"/>
    

    ...或者如果这不起作用(呵呵),为什么不将值作为字符串传递,然后在您的 api 控制器中解析它:

    using System.Globalization;
    
    // fetch the en-GB culture
    CultureInfo ukCulture = new CultureInfo("en-GB");
    // pass the DateTimeFormat information to DateTime.Parse
    DateTime myDateTime = DateTime.Parse("StringValue" ,ukCulture.DateTimeFormat);
    

    【讨论】:

    • 添加 uiCulture 似乎成功了!谢谢。
    • 抱歉,过激了。发布 09/08/2012 在服务器上显示日期为 2012 年 9 月 9 日。
    • 有很多地方我需要这样做,我希望有一种更全球化的方式来做到这一点,而不是为发布到我的 Api 控制器的每个模型解析日期。我已经看到用于 MVC 方面的自定义模型绑定器,但由于这是一个 Web Api 控制器,我不相信它使用模型绑定器(我正在使用 [FromUri])。
    • 很公平。我找不到任何不只是在 web.config 中设置文化和 uiCulture 的参考。希望你能找到一些东西。
    猜你喜欢
    • 2021-11-18
    • 1970-01-01
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多