代码之家  ›  专栏  ›  技术社区  ›  Paul Hinett

Asp.Net Web Api-发布英国日期格式

  •  8
  • Paul Hinett  · 技术社区  · 12 年前

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

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

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

    保罗

    3 回复  |  直到 12 年前
        1
  •  2
  •   Paul Hinett    12 年前

    使用自定义模型绑定器完成此操作,该绑定器与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属性,这些属性现在都是有效的英国日期时间。

        2
  •  2
  •   David Perlman    11 年前

    我也想在全球范围内解决这个问题。。。在这个过程中扯掉了很多头发。事实证明,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
  •  1
  •   Jude Fisher    12 年前

    这里有一个将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区域性(我不知道这是否会影响MVC中的jQuery捆绑包):

    <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);