9

Desidero creare un sito Web in diverse lingue. Ho già letto che avrei potuto creare un ActionFilter, ma ho un problema in piu ':
ho dovuto creare un ModelBinder personalizzato al fine di lavorare con i formati di numeri inglese e tedesco (123,456,789.1 vs. 123.456.789,1)Cambia cultura prima di utilizzare ModelBinder

public class DecimalModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     string key = bindingContext.ModelName; 
     var v = ((string[])bindingContext.ValueProvider.GetValue(key).RawValue)[0]; 
     float outPut; 
     if (float.TryParse(v, NumberStyles.Number, System.Globalization.CultureInfo.CurrentCulture, out outPut)) 
      return outPut; 
     return base.BindModel(controllerContext, bindingContext); 

    } 
} 

Questo ModelBinder utilizza la cultura corrente per decidere quale formato viene utilizzato. Ma sfortunatamente, ModelBinder viene usato prima che ActionFilter possa cambiare la cultura.

Come modificare la cultura prima del il modelloBinder diventa attivo?

risposta

7

È possibile implementare un modulo IHttp e impostare la cultura in BeginRequest, come visto here.

void context_BeginRequest(object sender, EventArgs e) 
{ 
    // eat the cookie (if any) and set the culture 
    if (HttpContext.Current.Request.Cookies["lang"] != null) 
    { 
     HttpCookie cookie = HttpContext.Current.Request.Cookies["lang"]; 
     string lang = cookie.Value; 
     var culture = new System.Globalization.CultureInfo(lang); 
     Thread.CurrentThread.CurrentCulture = culture; 
     Thread.CurrentThread.CurrentUICulture = culture; 
    } 
} 
+0

E 'di lavoro, grazie un sacco! Ma ho una domanda: lo sai, perché il codice viene eseguito 5 volte per richiesta? – Christopher

+0

Non sto ottenendo questo comportamento. Puoi aggiungere un orologio a ((System.Web.HttpApplication) (mittente)). Request.RawUrl e vedere se le richieste sono le stesse? – barry

+2

@Christopher Il codice viene eseguito una volta per richiesta (da cui il nome BeginRequest), quindi forse c'è una richiesta per la pagina e altre 4 per fogli di stile, immagini o file JavaScript. Controlla Request.Url, che potrebbe far luce. –

6

Io di solito impostare il CurrentCulture e CurrentUICulture gestendo l'evento PreRequestHandlerExecute in Global.asax.cs (si potrebbe anche gestire questo evento in un IHttpModule come suggerito da Barry).

Il punto è di farlo in un evento che si verifica prima che avvenga l'associazione del modello. Ci sono molti altri eventi che avvengono prima di questo che potresti utilizzare.

Consultare lo HttpApplication Class per informazioni sugli eventi disponibili e sull'ordine in cui vengono generati.

public class MvcApplication : HttpApplication 
    { 
     protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) 
     { 
      var culture = new CultureInfo("en-GB"); // Get the culture name from the route values/request querystring/form/cookie 
      Thread.CurrentThread.CurrentCulture = culture; 
      Thread.CurrentThread.CurrentUICulture = culture; 
     } 
    } 

si potrebbe anche farlo gestendo l'evento OnActionExecuting sul Controller (probabilmente desidera creare un controller di base e farlo lì, quindi sono tutti i controller di ereditare da questo controller di base).

public class MyBaseController : Controller 
    { 
     protected override void OnActionExecuting(ActionExecutingContext filterContext) 
     { 
      var culture = new CultureInfo("en-GB"); // Get the culture name from the route values/request querystring/form/cookie 
      Thread.CurrentThread.CurrentCulture = culture; 
      Thread.CurrentThread.CurrentUICulture = culture; 

      base.OnActionExecuting(filterContext); 
     } 
    } 

    public class MyController : MyBaseController 
    { 
     public ActionResult Index() 
     { 
      return View(); 
     } 
    } 
+12

-1: OnActionExecuting viene richiamato DOPO che il modello di associazione è stato richiamato. Quindi OnActionExecuting è troppo tardi. – Rookian

4

istanze di IAuthorizationFilter vengono eseguiti prima vincolante modello, permettendo così di impostare le culture necessarie