如果没有预先附加路线

时间:2015-09-17 10:27:03

标签: c# asp.net asp.net-mvc asp.net-mvc-4 asp.net-mvc-routing

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

  

URL:// {语言} - {培养} / {控制器} / {行动} / {ID}

通过这种方式,我们可以按照谷歌机器人正确抓取的语言生成网址:

  1. http://localhost/en-US/Home
  2. http://localhost/fr-FR/Home
  3. 翻译在两个地方实现。首先,我们使用以下方法修改了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返回“找不到路由”。如果用户忘记传递语言,我该如何传递该语言的默认参数?我虽然通过将默认值设置为路由配置就足够了,但它不起作用

1 个答案:

答案 0 :(得分:7)

您只需要另一条路线来处理没有第一段的情况。

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类处理的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());
    }
}