【问题标题】:Language-specific Default URL using MVC's Attribute Routing and RouteLocalization.mvc使用 MVC 的属性路由和 RouteLocalization.mvc 的语言特定的默认 URL
【发布时间】:2016-09-11 09:59:55
【问题描述】:

我希望能够为我的网站创建一个简洁的特定于语言的默认 URL,以便当有人浏览到:

somesite.com

他们被重定向到语言文化页面,例如:

  • somesite.com/en-US/
  • somesite.com/sp-MX/
  • somesite.com/fr-FR/

具体来说,我希望将 /Home/Index 附加到 URL:

  • somesite.com/en-US/Home/Index
  • somesite.com/sp-MX/Home/Index
  • somesite.com/fr-FR/Home/Index

我致力于使用 RouteLocalization.mvc 制作这个网站

我想在可行的范围内使用 MVC 属性路由

我无法弄清楚如何在不添加“索引”之类的内容的情况下将 Start() 方法重定向到特定于语言文化的 URL。

我尝试过的示例如下:

using RouteLocalization.Mvc;
using RouteLocalization.Mvc.Extensions;
using RouteLocalization.Mvc.Setup;

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.Clear();

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapMvcAttributeRoutes(Localization.LocalizationDirectRouteProvider);

        const string en = "en-us";
        ISet<string> acceptedCultures = new HashSet<string>() { en, "de", "fr", "es", "it" };

        routes.Localization(configuration =>
        {
            configuration.DefaultCulture = en;
            configuration.AcceptedCultures = acceptedCultures;
            configuration.AttributeRouteProcessing = AttributeRouteProcessing.AddAsNeutralAndDefaultCultureRoute;
            configuration.AddCultureAsRoutePrefix = true;
            configuration.AddTranslationToSimiliarUrls = true;
        }).TranslateInitialAttributeRoutes().Translate(localization =>
        {
            localization.AddRoutesTranslation();
        });

        CultureSensitiveHttpModule.GetCultureFromHttpContextDelegate = Localization.DetectCultureFromBrowserUserLanguages(acceptedCultures, en);

        var defaultCulture = System.Threading.Thread.CurrentThread.CurrentUICulture.Name;

        routes.MapRoute(
            name: "DefaultLocalized",
            url: "{culture}/{controller}/{action}/{id}",
            constraints: new { culture = @"(\w{2})|(\w{2}-\w{2})" }, 
            defaults: new { culture = defaultCulture, controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

还有我的家庭控制器:

public class HomeController : Controller
{
    [HttpGet]
    [Route]
    public RedirectToRouteResult Start()
    {
        return RedirectToAction("Home", new { culture = Thread.CurrentThread.CurrentCulture.Name });
    }

    [Route("Index", Name = "Home.Index")]
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Contact()
    {
        return View();
    }

    public ActionResult About()
    {
        return View();
    }
}

我的 Global.asax 文件:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {            
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        AreaRegistration.RegisterAllAreas();
    }
}

【问题讨论】:

    标签: asp.net asp.net-mvc asp.net-mvc-4 localization asp.net-mvc-routing


    【解决方案1】:

    重定向与路由不同。由于您将任何 URL 重定向到其本地化对应物的目标是一个跨领域问题,因此您最好的选择是制作一个全局过滤器。

    public class RedirectToUserLanguageFilter : IActionFilter
    {
        private readonly string defaultCulture;
        private readonly IEnumerable<string> supportedCultures;
    
        public RedirectToUserLanguageFilter(string defaultCulture, IEnumerable<string> supportedCultures)
        {
            if (string.IsNullOrEmpty(defaultCulture))
                throw new ArgumentNullException("defaultCulture");
            if (supportedCultures == null || !supportedCultures.Any())
                throw new ArgumentNullException("supportedCultures");
    
            this.defaultCulture = defaultCulture;
            this.supportedCultures = supportedCultures;
        }
    
        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var routeValues = filterContext.RequestContext.RouteData.Values;
    
            // If there is no value for culture, redirect
            if (routeValues != null && !routeValues.ContainsKey("culture"))
            {
                string culture = this.defaultCulture;
                var userLanguages = filterContext.HttpContext.Request.UserLanguages;
                if (userLanguages.Length > 0)
                {
                    foreach (string language in userLanguages.SelectMany(x => x.Split(';')))
                    {
                        // Check whether language is supported before setting it.
                        if (supportedCultures.Contains(language))
                        {
                            culture = language;
                            break;
                        }
                    }
                }
    
                // Add the culture to the route values
                routeValues.Add("culture", culture);
    
                filterContext.Result = new RedirectToRouteResult(routeValues);
            }
        }
    
        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            // Do nothing
        }
    }
    

    用法

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new RedirectToUserLanguageFilter("en", new string[] { "en", "de", "fr", "es", "it" }));
            filters.Add(new HandleErrorAttribute());
        }
    }
    

    另请注意,您的路由配置错误。每次应用程序启动都会运行一次路由设置,因此将默认文化设置为当前线程的文化是没有意义的。实际上,您根本不应该为您的文化路由设置默认文化,因为您希望它错过,所以如果没有文化集,您的 Default 路由将执行。

    routes.MapRoute(
        name: "DefaultLocalized",
        url: "{culture}/{controller}/{action}/{id}",
        constraints: new { culture = @"(\w{2})|(\w{2}-\w{2})" },
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
    
    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
    

    【讨论】:

    • 这个答案有效,它对我非常有帮助。我会投票赞成你的回答,但我没有足够的分数来投票。关于我配置错误的路线的注释非常有帮助,您的过滤器也是如此。我很快就会花更多时间来理解过滤器代码。非常感谢。
    猜你喜欢
    • 2013-01-16
    • 2011-04-10
    • 1970-01-01
    • 2018-08-23
    • 2014-01-28
    • 2018-01-14
    • 2018-10-12
    • 2013-12-29
    • 1970-01-01
    相关资源
    最近更新 更多