我在我的网络应用程序上有3种语言的本地化,方案是:当用户打开页面时,URL example.com但我想将它设为example.com/en。
我正在尝试使用RedirectToRouteResult
来实现它,但在第一次尝试打开页面时,我收到错误。我从这个article
我尝试实现此目的的主要原因是用户级别定义的文化信息,因此当来自一个国家/地区的用户设置他/她的语言时,他/她不必每次都重新执行此操作他们进入页面的时间,因为我将数据存储在缓存和数据库中;
并且OutputCache
因此当有人进入页面时,他们不会面对其他用户呈现的页面,这可能不是新用户的默认语言。
public class InternationalizationAttribute : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// This is a dummy constraint, if the culture is zz, it means that URL does not contain correct culture
bool redirectToLanguagedVersion = filterContext.RouteData.Values["culture"].ToString() == "zz";
string language = "en", culture = "GB";
if (redirectToLanguagedVersion)
{
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
var user = IdentityManager.GetUser(filterContext.HttpContext.User.Identity.GetUserId());
language = user.CultureInfoLanguage ?? language;
culture = user.CultureInfoCulture ?? culture;
}
else
{
language = filterContext.RequestContext.HttpContext.Cache["UserCultureInfoLanguage"]?.ToString() ?? language;
culture = filterContext.RequestContext.HttpContext.Cache["UserCultureInfoCulture"]?.ToString() ?? culture;
}
RouteValueDictionary values = filterContext.RouteData.Values;
values.Remove("culture");
values.Add("culture", culture);
filterContext.Result = new RedirectToRouteResult("DefaultWithCulture", values); // Issue hits here
}
else
{
// ... Define the culture user should use and update cache/db if needed
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture));
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture));
}
}}
这是RouteConfig
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Call to register your localized and default attribute routes
routes.MapLocalizedMvcAttributeRoutes(
urlPrefix: "{culture}/",
constraints: new { culture = new CultureConstraint(defaultCulture: "zz", pattern: "[a-z]{2}") }
);
routes.MapRoute(
name: "DefaultWithCulture",
url: "{culture}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { culture = new CultureConstraint(defaultCulture: "zz", pattern: "[a-z]{2}") }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { culture = "zz", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "TourWithCulture",
url: "{culture}/{controller}/{action}/{id}/{title}",
defaults: new { controller = "Tours", action = "Explore", id = UrlParameter.Optional, title = UrlParameter.Optional },
constraints: new { culture = new CultureConstraint(defaultCulture: "zz", pattern: "[a-z]{2}") }
);
routes.MapRoute(
name: "Tour",
url: "{controller}/{action}/{id}/{title}",
defaults: new { controller = "Tours", action = "Explore", id = UrlParameter.Optional, title = UrlParameter.Optional },
constraints: new { culture = new CultureConstraint(defaultCulture: "zz", pattern: "[a-z]{2}") }
);
}
}
答案 0 :(得分:0)
您获得异常的原因是您没有提供构建URL所需的匹配值。要构建URL,您需要提供所有必需的值(如果需要,还可以提供可选的值)。但是额外的值会导致它不匹配。
RouteValueDictionary values = filterContext.RouteData.Values;
values.Remove("culture");
values.Add("culture", culture);
filterContext.Result = new RedirectToRouteResult("DefaultWithCulture", values);
始终需要控制器和操作。所以,对于这条路线你需要通过:
这意味着如果您的路线值集合超过此值(例如title
),则与DefaultWithCulture
不匹配。请注意,DefaultWithCulture
是路径的额外条件,但您仍必须传递所有必需的路线值才能与之匹配。
也就是说,在使用基于this answer的路由时,您不应该将路由名称传递给RedirectToRouteResult
,因为事实上有2条路由代表可能的匹配 - DefaultWithCulture
和{{ 1}}在这种情况下。您必须删除匹配的额外名称条件,否则将无法匹配Default
。
Default