8

ユーザーが、2012年1月12日(2012年12月1日)などの英国形式でasp.netWebAPIコントローラーに日付を投稿できるようにしたいと思います。

私がデフォルトで言うことができることから、私たちのフォーマットだけが受け入れられます。

UKフォーマットがデフォルトになるようにどこかで何かを変更できますか?web.configでグローバリゼーション設定を変更しようとしましたが、効果がありませんでした。

ポール

4

3 に答える 3

2

これは、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ファイルに、次の行を追加して、DateTime値にこのモデルバインダーを使用するようにAPIに指示します。

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

これが私のAPIコントローラーのメソッドです:

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

私のLeadsIndexViewModelクラスにはいくつかのDateTimeプロパティがあり、これらはすべて有効な英国の日時になりました。

于 2012-08-30T13:03:50.907 に答える
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);
        }
    }
} 
于 2013-09-03T13:06:23.050 に答える
1

jQueryの日付ピッカーをen-gbにローカライズする例がここにあります:http ://weblogs.asp.net/hajan/archive/2010/10/05/integration-of-jquery-datepicker-in-asp-net-website -ローカリゼーション-part-3.aspx

また、カルチャをen-GBに設定しようとしたようですが、Web.ConfigでもUIカルチャを設定しようとしたかどうかはわかりません(これがMVCのjQueryバンドルに影響するかどうかはわかりません)。 )::

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

...またはそれが機能しない場合は(heh)、値を文字列として渡してから、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);
于 2012-08-30T11:21:28.343 に答える