5

Ich trat folgenden unerwünschten Verhalten bei der Verwendung "Remote" Validierungsattribut für eine bestimmte DateTime Model Eigenschaft.MVC Model Binding für DateTime unterscheidet sich mit GET oder POST

Server-Seite, meine Anwendung Kultur definiert wird, wie unten beschrieben:

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

-Client-Seite ist meine Anwendung Kultur definiert, wie unten beschrieben:

Globalize.culture("nl-BE"); 

Fall 1:

  • Modell Eigenschaft

    [Remote("IsDateValid", "Home")] 
    public DateTime? MyDate { get; set; } 
    
  • Controller Aktion

    public JsonResult IsDateValid(DateTime? MyDate) 
    { 
        // some validation code here 
        return Json(true, JsonRequestBehavior.AllowGet); 
    } 
    
  • Während das Debuggen des IsDateValid Methode, ein Datum in der Benutzeroberfläche eingegeben als 05/10/2013 (5. Oktober 2013) ist falsch interpretiert als 10/05/2013 (10. Mai 2013)

Fall 2:

  • Modell Eigentum

    [Remote("IsDateValid", "Home", HttpMethod = "POST")] 
    public DateTime? MyDate { get; set; } 
    
  • Controller Aktion

    [HttpPost] 
    public JsonResult IsDateValid(DateTime? MyDate) 
    { 
        // some validation code here 
        return Json(true); 
    } 
    
  • Während das Debuggen des IsDateValid Methode, ein Datum in der Benutzeroberfläche als 05/10/2013 (5. Oktober 2013) eingetragen ist richtig interpretiert als 05/10/2013 (5. Oktober 2013)

Ich vermisse etwas Konfiguration für mak die "Standard" -GET-Fernvalidierung wie gewünscht durchführen?

+0

Debug welcher Kultur verwendet wird, um das Datum in Sicht zu analysieren –

Antwort

8

Wenn Daten für GET gebunden werden, wird InvariantCulture verwendet (was "en-US" ist), während für POST Thread.CurrentThread.CurrentCulture ist. Der Grund dafür ist, dass GET-URLs von Benutzern gemeinsam genutzt werden können und daher invariant sein sollten. Während POST niemals geteilt wird, ist es sicher, die Kultur des Servers zu benutzen, um dort zu binden.

Wenn Sie sicher sind, dass Ihre Anwendung keine URLs zwischen Personen aus verschiedenen Ländern teilen muss, können Sie auch Ihre eigene ModelBinder erstellen, die dazu zwingt, das Server-Gebietsschema auch für GET-Anfragen zu verwenden. Hier

ist die Probe, wie es in Global.asax.cs aussehen:

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