5

Ho riscontrato un comportamento indesiderato durante l'utilizzo dell'attributo di convalida "Remote" per una determinata proprietà DateTime Model.Il binding del modello MVC per DateTime è diverso utilizzando GET o POST

lato server, la mia cultura Application è definita come descritto di seguito:

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

lato client, la mia cultura Application è definita come descritto di seguito:

Globalize.culture("nl-BE"); 

Caso 1:

  • Proprietà modello

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

    public JsonResult IsDateValid(DateTime? MyDate) 
    { 
        // some validation code here 
        return Json(true, JsonRequestBehavior.AllowGet); 
    } 
    
  • Durante il debug del metodo IsDateValid, una data inserita nella UI come 05/10/2013 (5 Ottobre 2013) è erroneamente interpretato come 10/05/2013 (10 Maggio 2013)

caso 2:

  • Modello Proprietà

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

    [HttpPost] 
    public JsonResult IsDateValid(DateTime? MyDate) 
    { 
        // some validation code here 
        return Json(true); 
    } 
    
  • Durante il debug del metodo IsDateValid, una data inserita nella UI come 05/10/2013 (5 Ottobre 2013) è correttamente interpretato come 05/10/2013 (5 Ottobre 2013)

Mi manca qualche configurazione per mak il lavoro di validazione remota "standard" GET come desiderato?

+0

Debug ciò che la cultura viene utilizzato per analizzare la data in vista –

risposta

8

Quando si utilizzano dati vincolanti per GET, viene utilizzato InvariantCulture (che è "en-US"), mentre per POST Thread.CurrentThread.CurrentCulture è. La ragione è che gli URL GET possono essere condivisi dagli utenti e quindi dovrebbero essere invariabili. Considerando che il POST non è mai condiviso ed è sicuro usare la cultura del server per legare lì.

Se sei sicuro che la tua applicazione non abbia bisogno dell'opzione di condivisione url tra persone provenienti da paesi diversi, sei sicuro di creare il tuo ModelBinder che imporrà di usare le impostazioni locali del server anche per le richieste GET.

Ecco il campione come può sembrare in 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; 
     } 
    } 
}