所以我有这个自定义路由,它根据 URL 中的文化设置路由表,但是当我调用 Url.Action(...) 时,它不会生成本地化 URL。任何想法我做错了什么?页面上的文化正在发生变化,我能够确定用户选择了什么语言,但 Url.Action 没有生成本地化 URL。
这是自定义路由,它会更改路由表的值(不确定是否采用这种标准方式):
public class CultureRoute : Route
{
public CultureRoute(string url, object defaults, object contraints)
: base(url, new MvcRouteHandler())
{
base.Defaults = CreateRouteValueDictionary(defaults);
base.Constraints = CreateRouteValueDictionary(contraints);
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var routeData = base.GetRouteData(httpContext);
if (routeData != null)
{
var culture = routeData.Values["culture"].ToString();
var cookie = httpContext.Request.Cookies["culture"];
var areEqual = false;
if (cookie == null || cookie.Value == "" || !(areEqual = string.Equals(culture, cookie.Value, StringComparison.OrdinalIgnoreCase)))
{
routeData.Values["culture"] = culture;
httpContext.Response.Cookies.Add(new HttpCookie("culture", culture));
}
else if (!areEqual)
{
routeData.Values["culture"] = cookie.Value;
}
CultureHelper.SetCurrentCulture(culture);
}
return routeData;
}
private static RouteValueDictionary CreateRouteValueDictionary(object values)
{
var dictionary = values as IDictionary<string, object>;
if (dictionary != null)
{
return new RouteValueDictionary(dictionary);
}
else
{
return new RouteValueDictionary(values);
}
}
}
和这个帮助类来设置线程文化:
public class CultureHelper
{
public static void SetCurrentCulture(string culture)
{
var info = CultureInfo.CreateSpecificCulture(culture);
Thread.CurrentThread.CurrentCulture = info;
Thread.CurrentThread.CurrentUICulture = info;
}
public static string GetCurrentCulture(bool ignoreRouteData = false)
{
if (!ignoreRouteData)
{
var routeData = HttpContext.Current.Request.RequestContext.RouteData;
object culture;
if (routeData.Values.TryGetValue("culture", out culture))
{
return culture.ToString();
}
}
var cookie = HttpContext.Current.Request.Cookies["culture"];
if (cookie != null && cookie.Value != null)
{
return cookie.Value;
}
return GetThreadCulture();
}
public static string GetThreadCulture()
{
var culture = Thread.CurrentThread.CurrentCulture.Name;
if (culture.IndexOf('-') > -1)
{
culture = culture.Substring(0, 2);
}
return culture;
}
}
还有 RouteConfig 类,它从 Global.asax 调用并使用我的自定义路由类设置路由:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add("Partial", new CultureRoute(
"{culture}/{cotroller}/partial/{view}",
new { culture = "ka", controller = "home", action = "partial", view = "" },
new { culture = "(ka|en)" }));
routes.Add("Default", new CultureRoute(
"{culture}/{controller}/{action}/{id}",
new { culture = "ka", controller = "home", action = "index", id = UrlParameter.Optional },
new { culture = "(ka|en)" }));
}
}
但是如果没有这种扩展方法,我将无法生成基于文化的路由,即 Url.Action 不会根据自定义路由类创建的路由表生成 URL:
public static string Action2(this UrlHelper helper, string action)
{
var culture = CultureHelper.GetThreadCulture();
return helper.Action(action, new { culture = culture });
}