5

對於某個DateTime模型屬性使用「遠程」驗證屬性時,遇到下列不想要的行爲。對於DateTime,MVC模型綁定使用GET或POST是不同的

服務器端,如下所述我的應用文化的定義:

Globalize.culture("nl-BE"); 

案例1:

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

客戶端,如下文所述我的應用文化的定義

  • 模型屬性

    [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日)的日期是錯誤解釋爲10/05/2013(2013年5月10日)

案例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(10月5日2013年)的日期是正確解釋爲05/10/2013(10月5日2013)

我是否缺少mak的一些配置根據需要進行「標準」GET遠程驗證工作?

+0

調試什麼文化被用來解析鑑於日期 –

回答

8

當爲GET綁定數據時,使用InvariantCulture(即「en-US」),而對於POST Thread.CurrentThread.CurrentCulture。背後的原因是,GET網址可能會被用戶共享,因此應該是不變的。儘管POST永遠不會共享,並且可以安全地使用服務器的文化進行綁定。

如果您確定您的應用程序不需要在來自不同國家/地區的人員之間共享URL的選項,那麼您可以安全地創建自己的ModelBinder,即使對於GET請求也會強制使用服務器區域設置。

下面是示例如何可能看起來像在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; 
     } 
    } 
}