如果不可用,则使用预附加路由

本文关键字:路由 如果不 | 更新日期: 2023-09-27 18:13:04

我们已经实现了一个本地化版本的ASP。. NET MVC网站,URL结构如下:

url://{语言}-{文化}/{控制器}/{行动}/{id}

通过这种方式,我们可以通过语言生成url,这些url可以被Google bot正确抓取:

  1. http://localhost/en-US/Home
  2. http://localhost/fr-FR/Home

翻译在两个地方完成。首先,我们用这个修改了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返回"路由未找到"。如果用户忘记传递语言的默认参数,我该如何传递?我认为通过将默认值设置为路由配置就足够了,但它不起作用

如果不可用,则使用预附加路由

你只需要另一个路由来处理没有第一段的情况。

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类处理的两个不同步骤。除非URL模式先匹配,否则不会填充路由值。

请注意,如果您使用动作过滤器来设置当前线程的区域设置,那么在模型绑定器中本地化将不可用。一种解决方法是使用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());
    }
}