2012-11-29 15 views
11

Ho aggiornato una soluzione MVC3 a MVC4. Dopo la migrazione, il validatore è rotto.DateTime discreto? Validazione in MVC

La mia data di inserimento, se si seleziona il tedesco come lingua, è "20.03.2013". Ottengo un errore di convalida in MVC4, ma non in MVC3. Se sostituisco il formato da "20.03.2013" a "20/03/2013" funziona in MVC4, ma non in MVC3 ;-)

Ho impostato la cultura dell'interfaccia utente del thread corrente in tedesco. L'output dei valori ResX è nella lingua corretta, , quindi so che non ci dovrebbero essere errori con la cultura., solo per il sito stesso. I messaggi di errore sono in inglese, ma il sito è in tedesco.

Suppongo che questo significhi che il validatore utilizza la Cultura dell'interfaccia utente sbagliata.

Ecco il codice che uso.

 
[Required(ErrorMessageResourceName = "Error_DepartureDate", ErrorMessageResourceType = typeof(Resx.Query))] 
public DateTime? DepartureDate { get; set; } 

Presumo ci sia qualcosa di sbagliato con il legante modello predefinito, come il rendering HTML sembra buono:

 
data-lang="de" data-mindate="3" data-val="true" data-val-required="Bitte geben Sie das gewünschte Reisedatum des Hinflugs ein." id="DepartureDate" name="DepartureDate" tabindex="3" type="text" value="" 

ho aggiornato il JScript per le fonti che la nave quando si crea una nuova applicazione MVC utilizzando i modelli di Visual Studio 2012 (SP1 è installato). Questo non ha avuto impatto.

Ho un oggetto CultureModelBinder che legge la cultura corrente dalla sessione e imposta la cultura utilizzando una piccola funzione di supporto.

 
public static void UpdateThreadCulture(CultureInfo culture) 
{ 
    Thread.CurrentThread.CurrentUICulture = culture;    
}   

Il raccoglitore modello cultura è il raccoglitore predefinito.

 
ModelBinders.Binders.DefaultBinder = new CultureModelBinder(); 
ModelBinders.Binders.Add(typeof(DateTime?), new DateTimeModelBinder()); 
// and many, many more 

Forse qualcosa cambiato nell'ordine di esecuzione con mvc4 ha causato il problema?

Aggiornamento: il progetto utilizza .NET Framework 4.5 come destinazione.

Aggiornamento 2:

ho una casella combinata in cui l'utente può selezionare 16 lingue diverse, ognuno potrebbe avere un proprio formattazione specifica.

E.g. DE-de -> GG.MM.AAAA; it-it -> GG/MM/AAAA; it-it -> MM/DD/YYYY

Ho appena ricevuto un suggerimento su come impostare la cultura attuale, ecco la prova che dovrebbe essere corretta così com'è. Questo codice non viene colpito quando i validatori falliscono, sembra che accada sul lato client.

 
    public class DateTimeModelBinder : IModelBinder 
    { 
     private LogService _log = new LogService(); 

     public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
     {    
      object result = null; 
      ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
      if (valueResult != null) 
      { 
       try 
       { 
        var stateHandler = new StateHandler(controllerContext.HttpContext.Session);      
        result = valueResult.ConvertTo(typeof(DateTime?), stateHandler.Culture);          
       } 
       catch 
       { 
        try 
        { 
         result = valueResult.ConvertTo(typeof(DateTime?), CultureInfo.InvariantCulture); 
        } 
        catch (Exception ex) 
        { 
         _log.Error("DateTimeModelBinder parse exception", ex); 
         _log.KeyValue("AttemptedValue", valueResult.AttemptedValue);           
        }      
       } 
      } 
      return result; 
     } 
    } 

e per completezza il mio modello di cultura legante:

 
    public class CultureModelBinder : DefaultModelBinder 
    {  
     public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
     { 
      StateHandler stateHandler = new StateHandler(controllerContext.HttpContext.Session); 
      Helper.UpdateThreadCulture(stateHandler.Culture); 

      return base.BindModel(controllerContext, bindingContext); 
     }   
    } 

Aggiornamento: Forse c'è una correlazione a questo problema: http://connect.microsoft.com/VisualStudio/feedback/details/705643/a-data-val-date-attribute-is-generated-for-time-fields-in-asp-net-mvc-4

Aggiornamento: Leggere il seguente articolo: http://weblogs.asp.net/scottgu/archive/2010/06/10/jquery-globalization-plugin-from-microsoft.aspx

ha provato quanto segue:

Loaded gli script nel seguente ordine:

 
/Scripts/jquery-1.8.3.min.js 
/Scripts/globalize.js 
/Scripts/cultures/globalize.cultures.js 
// and much more other scripts... 

aggiunto la chiamata. l'output era correttamente "DE".

 
     var currentLanguage = $("#DepartureDate").attr("data-lang"); 
     alert(currentLanguage);  
     $.preferCulture(currentLanguage); 

alcun effetto per i validatori ...

+0

Possibile duplicato della mia domanda: P http://stackoverflow.com/questions/11756226/dot-separated-clientside-date-validation-in-asp-mvc-4/11771781#11771781 –

+0

Thx, ho visto la tua domanda Non uso il pacchetto. Era un aggiornamento 1: 1 da MVC3 a MVC4. Ho provato anche a creare un nuovo progetto MVC4 dal modello e ho lo stesso problema. Ho rimosso quindi il bundle e questo non ha avuto alcun impatto. – NickD

+0

Hai sovrascritto il validatore della data jquery predefinito come visualizzato nella domanda? –

risposta

10

Il punto è che MVC3 doesnt convalidare in tutte le date sul lato client che è il punto. Hai appena impostato la cultrure sul lato server ... ma le impostazioni della tua cultura non si riflettono sul lato client ... almeno il motore Mvc non lo fa automaticamente. L'unico modo per gestire correttamente date e numeri sul lato client con culture diverse dall'inglese è utilizzare una libreria di globalizzazione javascript che sia in grado di analizzare correttamente le date in tutte le culture e impostare la cultura lato client uguale alla cultura lato server , quindi è necessario ridefinire correttamente tutti i metodi di convalida per utilizzare le funzioni globalizzate. Si prega di leggere questo post del mio blog che chiarisce come gestire correttamente la globalizzazione sul lato client: http://www.dotnet-programming.com/post/2011/12/14/Globalization-Validation-and-DateNumber-Formats-in-AspNet-MVC.aspx

Inoltre, per favore non confondete CurrentCulture con CurrentUICulture CurrentUICulture non interessa a tutti i numeri modo o date sono gestite, ma solo la risorsa file contenenti risorse specifiche della cultura come stringhe localizzate.

Infine, è molto inefficiente impostare la cultura nel raccoglitore modello, poiché il legatore modello è una funzione ricorsiva, quindi viene chiamato centinaia di volte durante la ricostruzione del modello e l'operazione di impostazione cultura non è un'operazione di impostazione di una variabile semplice ma ha un costo non trascurabile. È preferibile scrivere un filtro del controller globale per gestire l'impostazione della cultura (faccio sempre così) l'operazione viene eseguita solo una volta per richiesta

+0

Grazie , ci proveremo domani ;-) – NickD

+0

Ha risparmiato un sacco di tempo !!! Grazie! – Andrei

3

Prova sovrascrivendo la data predefinita validatore:

// Replace dots so jq validator can understand what's going on 
$(function() { 
    $.validator.addMethod(
    "date", 
    function (value, element) { 
     var s = value; 
     s = value.replace(/\./g, '/'); 

     // Chrome requires tolocaledatestring conversion, otherwise just use the slashed format 
     var d = new Date(); 
     return this.optional(element) || !/Invalid|NaN/.test(new Date(d.toLocaleDateString(value))) || !/Invalid|NaN/.test(new Date(s)); 
    }, 
    "" 
    ); 
}); 

$.validator.unobtrusive.parse(); 
+0

Grazie, Sto provando a farlo, spero di trovare una soluzione senza modificare troppo codice. Come detto, funziona con MVC3 senza problemi – NickD

+1

Lo so e mi piacerebbe davvero sapere qual è il problema esattamente, questa validazione/formattazione client datepicker mi ha causato così tanto mal di testa che è incredibile.Questa cosa in realtà non dovrebbe essere necessaria –

+0

Potrei prendere in considerazione questa soluzione in combinazione con un raccoglitore di modelli personalizzato.Posso formattare la data in formato Ansi Date per tutte le culture e utilizzare il sovraccarico datetime dove posso passare anno, mese e giorno separatamente.Ma aspettiamo e vediamo se ci sono soluzioni migliori: D – NickD

0

Microsoft consiglia di sostituire il nuovo jquery.validate.js da mvc4 con il vecchio jQuery .validate.js dal modello di progetto MVC3. Funziona, ma la cosa divertente è che il bug non è in MVC4, era in MVC3.

Usiamo il modo in cui è stato descritto da Francesco, vedere la risposta accettata.

0

Se ciò si verifica solo in Chrome, è dovuto alla versione jquery che ha un bug di coltura nella convalida delle date.

+0

No, è in tutti i browser. Funziona ora corretto. – NickD

2

Guardando attraverso il codice con ILSpy sembra essere il ClientDataTypeModelValidatorProvider appena introdotto che sta aggiungendo l'attributo data-val-date.

Se si desidera ripristinare le funzionalità in stile MVC3, è sufficiente rimuovere tale provider dall'elenco dei provider di convalida del modello.

Non risolve il problema ma in alcune righe di codice può rimuovere i problemi causati dalla mancanza di globalizzazione della validazione jquery.

using System.Web.Mvc; 

... 

protected void Application_Start() 
{ 
    var providers = ModelValidatorProviders.Providers; 
    var clientDataTypeModelValidatorProvider = providers.OfType<ClientDataTypeModelValidatorProvider>().FirstOrDefault(); 
    if (clientDataTypeModelValidatorProvider != null) 
    { 
    providers.Remove(clientDataTypeModelValidatorProvider); 
    } 

    ... 
} 
Problemi correlati