6

特定の DateTime モデル プロパティに「リモート」検証属性を使用しているときに、次の望ましくない動作が発生しました。

サーバー側では、私のアプリケーション カルチャは以下のように定義されています。

protected void Application_PreRequestHandlerExecute()
{
    if (!(Context.Handler is IRequiresSessionState)){ return; }
    Thread.CurrentThread.CurrentCulture = new CultureInfo("nl-BE");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("nl-BE");
}

クライアント側では、私のアプリケーション カルチャは以下のように定義されています。

Globalize.culture("nl-BE");

ケース 1:

  • モデル プロパティ

    [Remote("IsDateValid", "Home")]
    public DateTime? MyDate { get; set; }
    
  • コントローラ アクション

    public JsonResult IsDateValid(DateTime? MyDate)
    {
        // some validation code here
        return Json(true, JsonRequestBehavior.AllowGet);
    }
    
  • メソッドのデバッグ中IsDateValidに、UI に05/10/2013(2013 年 10 月 5 日) として入力された日付が (2013 年5 月 10 日)として誤って解釈される10/05/2013

ケース 2:

  • モデル プロパティ

    [Remote("IsDateValid", "Home", HttpMethod = "POST")]
    public DateTime? MyDate { get; set; }
    
  • コントローラ アクション

    [HttpPost]
    public JsonResult IsDateValid(DateTime? MyDate)
    {
        // some validation code here
        return Json(true);
    }
    
  • メソッドのデバッグ中IsDateValidに、UI に05/10/2013(2013 年 10 月 5 日) として入力された日付が (2013 年 10 月 5 日)として正しく解釈されます。05/10/2013

「標準」の GET リモート検証を希望どおりに機能させるための構成が不足していますか?

4

1 に答える 1

10

GET のデータをバインドする場合InvariantCulture(「en-US」) が使用されますが、POST の場合は使用されThread.CurrentThread.CurrentCultureます。背後にある理由は、GET URL はユーザーによって共有される可能性があるため、不変でなければならないからです。POST は決して共有されず、サーバーのカルチャを使用してそこにバインドしても安全です。

あなたのアプリケーションが異なる国の人々の間で URL を共有するオプションを必要としないことが確実であれば、ModelBinderGET リクエストに対してもサーバー ロケールを使用することを強制する独自のアプリケーションを安全に作成できます。

以下は、Global.asax.cs でどのように表示されるかのサンプルです。

protected void Application_Start()
{
    /*some code*/

    ModelBinders.Binders.Add(typeof(DateTime), new DateTimeModelBinder());
    ModelBinders.Binders.Add(typeof(DateTime?), new DateTimeModelBinder());
}

/// <summary>
/// Allows to pass date using get using current server's culture instead of invariant culture.
/// </summary>
public class DateTimeModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        var date = valueProviderResult.AttemptedValue;

        if (String.IsNullOrEmpty(date))
        {
            return null;
        }

        bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);

        try
        {
            // Parse DateTimeusing current culture.
            return DateTime.Parse(date);
        }
        catch (Exception)
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, String.Format("\"{0}\" is invalid.", bindingContext.ModelName));
            return null;
        }
    }
}
于 2013-11-29T11:49:10.637 に答える