2013-07-17 8 views
6

Si scopre che MVC DefaultModelBinder utilizza diverse culture per analizzare i valori (ad esempio double, DateTime, ecc.) Per le richieste POST e GET. Here è più informazioni.Come impostare la cultura di tutti i ValueProviderResult utilizzati nel binding del modello su un valore dato?

Vedo che questo è controllato dalla proprietà Culture degli oggetti ValueProviderResult, che vengono restituiti da IValueProvider.GetValue().

La mia domanda è: Come posso accertarmi globalmente che questo valore sia sempre CultureInfo.InvariantCulture.

So di poter implementare provider di valori personalizzati e farlo in questo modo.

So di poter implementare i raccoglitori modello personalizzati e farlo in questo modo.

So che posso impostare la cultura nel thread, ma sfortunatamente questa non è un'opzione nel mio caso.

Quello che sto cercando è un modo per impostarlo in modo che anche il raccoglitore modello predefinito ei fornitori di valori esistenti siano in grado di analizzare in modo invariante la cultura, indipendentemente da quale sia la cultura del thread impostata.

risposta

4

Per quanto ne so, non c'è modo che soddisfi i criteri. È fare una delle cose che sai che puoi fare (direi che il modo più appropriato sarebbe un fornitore di valore personalizzato).

Motivo: tutti i ValueProvider predefiniti sono codificati per l'uso di CultureInfo.InvariantCulture o CultureInfo.CurrentCulture.

Qui, in particolare, è il modo FormValueProvider fa:

internal FormValueProvider(
      ControllerContext controllerContext, 
      IUnvalidatedRequestValues unvalidatedValues 
     ) 
     : base(
       controllerContext.HttpContext.Request.Form, 
       unvalidatedValues.Form, 
       CultureInfo.CurrentCulture // <--- Grrr, argh 
     ) 
{ 
} 

La cultura non viene recuperato da altrove (cioè, l'argomento di cui sopra non è utilizzato come valore predefinito, ma come una cultura usare).

culture dei diversi IValueProviders

Per riferimento, che sono le colture per ciascuna delle IValueProviders predefiniti:

  • ChildActionValueProvider: InvariantCulture
  • FormValueProvider: CurrentCulture
  • JsonValueProvider : CurrentCulture
  • RouteDataValueProvider: InvariantCulture
  • QueryStringValueProvider: InvariantCulture
  • HttpFileCollectionValueProvider: InvariantCulture

Sostituzione delle CurrentCulture IValueProviders

Non è un compito immane per sostituire FormValueProvider, dal momento che, come si è visto sopra, chiama semplicemente la sua classe base '(NameValueCollectionValueProvider) costruttore - che prende la cultura desiderata come argomento.

L'implementazione originale di FormValueProvider appare sulla superficie per essere più difficile di quanto sia in realtà, con riferimenti a classi e interfacce interne. Ma non sono necessari per sostituire il fornitore: sono lì solo per i test unitari.

È solo bisogno di chiamare il costruttore di base (come detto sopra), passando due NameValueCollection s che sono facili da acquisire: Request.Forms e la proprietà di FormsValidation.Unvalidated(Request) (un metodo statico). E imposta il terzo argomento sulla cultura che desideri.

FormValueProviderFactory è ancora più semplice.

JsonValueProvider è un po 'più coinvolti - in sostanza che avrebbe dovuto copiare il codice sorgente di JsonValueProviderFactory ad una nuova classe e modificarlo - perché anche se permette prioritario GetValueProvider(), tale metodo consiste principalmente di chiamate verso altri private static metodi.

EDIT (Petar Ivanov): Questo ha funzionato per me. Per farlo funzionare non è stato sufficiente aggiungere la factory personalizzata a ValueProviderFactories.Factories, perché in questo modo viene aggiunta dopo lo FormValueProviderFactory. Invece, ho dovuto sostituire il FormValueProviderFactory con quello personalizzato.

+0

grazie per la risposta. Immagino di non essere sicuro di quale dei provider di default utilizzi CurrentCulture (e quindi ho bisogno di estenderlo), quindi stavo cercando una soluzione più generale. –

+0

Aggiunta la lista. Ho rimosso 'Session' e' TempData' - quelli sono parte di MVC Futures e quindi non sono usati di default - lo stesso vale per 'Cookie' e' ServerVariable'. Tutti usano "InvariantCulture". – JimmiTh

Problemi correlati