【发布时间】:2010-03-08 17:16:03
【问题描述】:
在 ASP.NET MVC 2 应用程序中,我的路由如下:
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)
}
现在,基本上我想根据传入的语言设置线程的文化。但有一个例外: 如果用户第一次请求该页面,例如调用“http://www.mysite.com”,我想尽可能将初始语言设置为“浏览器首选”。
如果由于默认值而设置了默认参数或通过 URL 明确提及,我如何在早期处理阶段(如 global.asax)区分? (我更喜欢不解析请求 URL 的解决方案)。
有没有办法为参数动态提供默认值?钩子之类的东西?或者我可以在哪里覆盖默认值(好的应用程序事件?)。
这是我实际试验的代码:
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);
}
}
重现示例的 RouteConstraint:
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;
}
}
}
有人可以帮我解决这个问题吗?
谢谢,马丁
【问题讨论】:
标签: asp.net-mvc localization multilingual default-value routes