2010-03-08 10 views
1

Dans une application ASP.NET MVC 2, je vais avoir une route comme ceci:ASP.NET MVC 2/Localisation/Valeur par défaut dynamique?

  routes.MapRoute(
      "Default",          // Route name 
      "{lang}/{controller}/{action}/{id}",    // URL with parameters 
      new            // Parameter defaults 
      {            
       controller = "Home", 
       action = "Index", 
       lang = "de", 
       id = UrlParameter.Optional 
      }, 
      new 
      { 
       lang = new AllowedValuesRouteConstraint(new string[] { "de", "en", "fr", "it" }, 
                 StringComparison.InvariantCultureIgnoreCase) 
      } 

Maintenant, au fond, je voudrais définir la culture du fil selon la langue adoptée en Mais il y a une exception.: Si l'utilisateur demande la page pour la première fois, comme appeler « http://www.mysite.com » Je veux définir la langue initiale, si possible, à celui « préféré par le navigateur ».

Comment puis-je distinguer dans un stade Procesing précoce (comme global.asax), si le paramètre par défaut a été défini en raison de la valeur par défaut ou mentionnée explicitement dans l'URL? (Je préférerais une solution où l'URL de demande ne serait pas analysée).

est-il un moyen de fournir dynamiquement une valeur par défaut pour un paramter? Quelque chose comme un crochet? Ou où puis-je remplacer la valeur par défaut (bon événement d'application?).

C'est le code que je suis en fait expérimentent:

 protected void Application_AcquireRequestState(object sender, EventArgs e) 
    { 
     string activeLanguage; 
     string[] validLanguages; 
     string defaultLanguage; 
     string browsersPreferredLanguage; 

     try 
     { 
      HttpContextBase contextBase = new HttpContextWrapper(Context); 
      RouteData activeRoute = RouteTable.Routes.GetRouteData(new HttpContextWrapper(Context));     

      if (activeRoute == null) 
      { 
       return; 
      } 

      activeLanguage = activeRoute.GetRequiredString("lang"); 
      Route route = (Route)activeRoute.Route; 
      validLanguages = ((AllowedValuesRouteConstraint)route.Constraints["lang"]).AllowedValues; 
      defaultLanguage = route.Defaults["lang"].ToString(); 
      browsersPreferredLanguage = GetBrowsersPreferredLanguage(); 

      //TODO: Better way than parsing the url 
      bool defaultInitialized = contextBase.Request.Url.ToString().IndexOf(string.Format("/{0}/", defaultLanguage), StringComparison.InvariantCultureIgnoreCase) > -1; 
      string languageToActivate = defaultLanguage; 
      if (!defaultInitialized) 
      { 
       if (validLanguages.Contains(browsersPreferredLanguage, StringComparer.InvariantCultureIgnoreCase)) 
       { 
        languageToActivate = browsersPreferredLanguage; 
       } 
      } 

      //TODO: Where and how to overwrtie the default value that it gets passed to the controller? 
      contextBase.RewritePath(contextBase.Request.Path.Replace("/de/", "/en/")); 

      SetLanguage(languageToActivate); 
     } 
     catch (Exception ex) 
     { 
      //TODO: Log 
      Console.WriteLine(ex.Message); 
     } 

    } 
    protected string GetBrowsersPreferredLanguage() 
    { 
     string acceptedLang = string.Empty; 

     if (HttpContext.Current.Request.UserLanguages != null && HttpContext.Current.Request.UserLanguages.Length > 0) 
     { 
      acceptedLang = HttpContext.Current.Request.UserLanguages[0].Substring(0, 2); 
     } 

     return acceptedLang; 
    } 

    protected void SetLanguage(string languageToActivate) 
    { 
     CultureInfo cultureInfo = new CultureInfo(languageToActivate); 

     if (!Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName.Equals(languageToActivate, StringComparison.InvariantCultureIgnoreCase)) 
     { 
      Thread.CurrentThread.CurrentUICulture = cultureInfo; 
     } 

     if (!Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName.Equals(languageToActivate, StringComparison.InvariantCultureIgnoreCase)) 
     { 
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name); 
     } 
    } 

Le RouteConstraint pour reproduire l'échantillon:

public class AllowedValuesRouteConstraint : IRouteConstraint 
{ 

    private string[] _allowedValues; 
    private StringComparison _stringComparism; 

    public string[] AllowedValues 
    { 
     get { return _allowedValues; } 
    } 

    public AllowedValuesRouteConstraint(string[] allowedValues, StringComparison stringComparism) 
    { 
     _allowedValues = allowedValues; 
     _stringComparism = stringComparism; 
    } 

    public AllowedValuesRouteConstraint(string[] allowedValues) 
    { 
     _allowedValues = allowedValues; 
     _stringComparism = StringComparison.InvariantCultureIgnoreCase; 
    } 

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 
    { 
     if (_allowedValues != null) 
     { 
      return _allowedValues.Any(a => a.Equals(values[parameterName].ToString(), _stringComparism)); 
     } 
     else 
     { 
      return false; 
     } 
    } 
} 

que quelqu'un peut me aider avec ce problème?

Merci, Martin

Répondre

0

Pour éviter d'être incompatibles, je préfère faire une redirection sur la racine de la langue du navigateur, puis laisser l'utilisateur changer la langue s'il/elle préfère.

mis simplement ces lignes dans default.aspx et vous êtes bon pour aller.

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 

    Select Case Mid(Request.UserLanguages(0).ToString(), 1, 2).ToLower 
     Case "en" 
      Response.Redirect("/en/") 
     Case "pt" 
      Response.Redirect("/pt/") 
     Case Else 
      Response.Redirect("/es/") 
    End Select 

End Sub 
+0

si quelqu'un accède à la page comme Posts.aspx permet de dire et non le Default.aspx. ça ne marchera pas. Cela devrait être sur un httpmodule ou le global.asax. –

+0

Il ne fonctionnera pas avec votre itinéraire non plus. –

0

Comment utiliser un filtre d'action?

il pourrait être quelque chose comme ceci:

public class LocalizationAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if (filterContext.RouteData.Values["lang"] != null) 
     { 
      var lang = filterContext.RouteData.Values["lang"].ToString(); 
      //TODO: Validate the obtained value. 
      Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(lang); 
     } 
     else 
     { 
      var langHeader = filterContext.HttpContext.Request.UserLanguages[0]; 
      //TODO: Validate the obtained value. 
      Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(langHeader); 
     } 
    } 
} 

Ceci est juste une idée, bien sûr, vous devez améliorer. Ensuite, vous ajoutez simplement cet attribut à vos contrôleurs ou vous créez un contrôleur de base et définissez l'attribut (et faites de tous vos contrôleurs une sous-classe de ce contrôleur de base).

Cordialement.

+0

Merci pour votre suggestion. Lorsque j'utilise une valeur par défaut pour lang dans la route par défaut, "lang" ne sera jamais nul. Si j'entre "ru" par exemple, j'obtiens un 404 ce qui est correct (voir la contrainte). Mais comment puis-je déterminer, si "de" est venu comme valeur par défaut ou transmis explicitement? Je veux seulement prendre la langue de navigateur si aucune valeur passée explicitement (si possible pas en analysant l'URL). Le deuxième problème que j'aurais alors est de changer le paramètre "lang", de sorte que tous les liens rendus obtiennent une URL mise à jour. – martinoss

+0

Exemple: - J'ai une valeur par défaut de "de" pour le param "lang" - Maintenant, je saisis "http://www.monsite.com" - Tous mes liens ressemble à ceci: http: // www .mysite.com/de/about Supposons maintenant que mon navigateur préfère "en" et j'appelle le "http://www.mysite.com". - La langue par défaut devrait maintenant être remplacée par "en" - Les liens devraient être rendus comme http://www.monsite.com/en/about – martinoss

+0

Oui, vous avez raison, désolé pour cela. Peut-être que vous devriez plutôt créer votre propre gestionnaire d'itinéraire à la place. Bonne chance! – uvita

0

essayez ceci:

 RouteData data=RouteTable.Routes.GetRouteData(httpContext); 
     if (data != null) 
     { 
      Route route = data.Route as Route; 
      if (route != null && route.Defaults != null) 
       route.Defaults["lang"] = lang.Name; 
     }