如果不可用,请预先附加路由
Pre-Append Route if not available
我们已经实施了 ASP.NET MVC 网站的本地化版本,该网站具有如下 URL 结构:
url://{language}-{culture}/{controller}/{action}/{id}
通过这种方式,我们可以通过 Google 机器人正确抓取的语言生成 URLs:
翻译是在两个地方实现的。首先我们把MVC的默认路由修改成这个:
routes.MapRoute(
name: "Default",
url: "{language}-{culture}/{controller}/{action}/{id}",
defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional,
language = "en",
culture = "US"
}
);
然后我们创建了一个操作过滤器,它切换到 URL 中可用的当前语言,如果不可用则切换到默认语言:
public class LocalizationAttribute : ActionFilterAttribute
{ public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string language = (string)filterContext.RouteData.Values["language"] ?? "en";
string culture = (string)filterContext.RouteData.Values["culture"] ?? "US";
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture));
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture));
}
}
}
如果用户输入 http://localhost/Whatever,就会出现问题。 ASP.NET MVC returns "Route not found"。如果用户忘记传递语言的默认参数,我该如何传递?我虽然通过将默认值设置到路由配置中就足够了,但它不起作用
您只需要另一条路线来处理没有第一段的情况。
routes.MapRoute(
name: "Default-Localized",
url: "{language}-{culture}/{controller}/{action}/{id}",
defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new
{
language = "en",
culture = "US",
controller = "Home",
action = "Index",
id = UrlParameter.Optional
}
);
匹配 URL 模式和构建路由值集合(基于默认值或可以覆盖它们的占位符)是由 Route
class 处理的 2 个不同步骤.除非 URL 模式首先匹配,否则不会填充路由值。
请注意,如果您使用操作过滤器来设置当前线程的区域设置 localization won't be available inside of the model binder。一种解决方法是使用 IAuthorizationFilter
而不是 ActionFilterAttribute
.
using System.Globalization;
using System.Threading;
using System.Web.Mvc;
public class LocalizationFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
var values = filterContext.RouteData.Values;
string language = (string)values["language"] ?? "en";
string culture = (string)values["culture"] ?? "US";
CultureInfo ci= CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture));
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
}
}
然后将其添加为全局过滤器。
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new LocalizationFilter());
filters.Add(new HandleErrorAttribute());
}
}
我们已经实施了 ASP.NET MVC 网站的本地化版本,该网站具有如下 URL 结构:
url://{language}-{culture}/{controller}/{action}/{id}
通过这种方式,我们可以通过 Google 机器人正确抓取的语言生成 URLs:
翻译是在两个地方实现的。首先我们把MVC的默认路由修改成这个:
routes.MapRoute(
name: "Default",
url: "{language}-{culture}/{controller}/{action}/{id}",
defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional,
language = "en",
culture = "US"
}
);
然后我们创建了一个操作过滤器,它切换到 URL 中可用的当前语言,如果不可用则切换到默认语言:
public class LocalizationAttribute : ActionFilterAttribute
{ public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string language = (string)filterContext.RouteData.Values["language"] ?? "en";
string culture = (string)filterContext.RouteData.Values["culture"] ?? "US";
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture));
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture));
}
}
}
如果用户输入 http://localhost/Whatever,就会出现问题。 ASP.NET MVC returns "Route not found"。如果用户忘记传递语言的默认参数,我该如何传递?我虽然通过将默认值设置到路由配置中就足够了,但它不起作用
您只需要另一条路线来处理没有第一段的情况。
routes.MapRoute(
name: "Default-Localized",
url: "{language}-{culture}/{controller}/{action}/{id}",
defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new
{
language = "en",
culture = "US",
controller = "Home",
action = "Index",
id = UrlParameter.Optional
}
);
匹配 URL 模式和构建路由值集合(基于默认值或可以覆盖它们的占位符)是由 Route
class 处理的 2 个不同步骤.除非 URL 模式首先匹配,否则不会填充路由值。
请注意,如果您使用操作过滤器来设置当前线程的区域设置 localization won't be available inside of the model binder。一种解决方法是使用 IAuthorizationFilter
而不是 ActionFilterAttribute
.
using System.Globalization;
using System.Threading;
using System.Web.Mvc;
public class LocalizationFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
var values = filterContext.RouteData.Values;
string language = (string)values["language"] ?? "en";
string culture = (string)values["culture"] ?? "US";
CultureInfo ci= CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture));
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
}
}
然后将其添加为全局过滤器。
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new LocalizationFilter());
filters.Add(new HandleErrorAttribute());
}
}