特定于语言的默认URL中使用MVC的属性路由和RouteLocalization.mvc [英] Language-specific Default URL using MVC's Attribute Routing and RouteLocalization.mvc

查看:292
本文介绍了特定于语言的默认URL中使用MVC的属性路由和RouteLocalization.mvc的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

somesite.com

他们重定向到一个语言文化的网页,例如:


  • somesite.com/en-US /

  • somesite.com/sp-MX /

  • somesite.com/fr-FR /

具体来说,我的想的 /主页/索引的追加到网址:


  • somesite.com/en-US/Home/Index

  • somesite.com/sp-MX/Home/Index

  • somesite.com/fr-FR/Home/Index

我致力于使使用RouteLocalization.mvc本网站

和我想用的 MVC属性路由的的范围内是可行的。

我有麻烦搞清楚如何使Start()方法重定向到一个语言文化特定的URL没有加入像指数。

我试图跟踪样本:

 使用RouteLocalization.Mvc;
使用RouteLocalization.Mvc.Extensions;
使用RouteLocalization.Mvc.Setup;公共类RouteConfig
{
    公共静态无效的RegisterRoutes(RouteCollection路线)
    {
        routes.Clear();        routes.IgnoreRoute({}资源个.axd / {*} PATHINFO);        routes.MapMvcAttributeRoutes(Localization.LocalizationDirectRouteProvider);        常量字符串EN =EN-US;
        ISet的<串GT; acceptedCultures =新的HashSet<串GT;(){恩,德,FR,ES,它};        routes.Localization(配置=>
        {
            configuration.DefaultCulture = EN;
            configuration.AcceptedCultures = acceptedCultures;
            configuration.AttributeRouteProcessing = At​​tributeRouteProcessing.AddAsNeutralAndDefaultCultureRoute;
            configuration.AddCultureAsRoute preFIX = TRUE;
            configuration.AddTranslationToSimiliarUrls = TRUE;
        })TranslateInitialAttributeRoutes()翻译(本地化=过夜。;
        {
            localization.AddRoutesTranslation();
        });        CultureSensitiveHttpModule.GetCultureFromHttpContextDelegate = Localization.DetectCultureFromBrowserUserLanguages​​(acceptedCultures,EN);        VAR defaultCulture = System.Threading.Thread.CurrentThread.CurrentUICulture.Name;        routes.MapRoute(
            名称:DefaultLocalized
            网址:{文化} / {控制器} / {行动} / {ID}
            限制:新{文化= @(\\ w {2})|(\\ w {2} - \\ w {2})},
            默认:新{文化= defaultCulture,控制器=家,行动=索引,ID = UrlParameter.Optional}
        );        routes.MapRoute(
            名称:默认,
            网址:{控制器} / {行动} / {ID}
            默认:新{控制器=家,行动=索引,ID = UrlParameter.Optional}
        );
    }
}

和我家的控制器:

 公共类HomeController的:控制器
{
    [HTTPGET]
    [路线]
    公共RedirectToRouteResult开始()
    {
        返回RedirectToAction(家,新的{文化= Thread.CurrentThread.CurrentCulture.Name});
    }    [路线(指数,名称=Home.Index)]
    公众的ActionResult指数()
    {
        返回查看();
    }    公众的ActionResult联系()
    {
        返回查看();
    }    公众的ActionResult关于()
    {
        返回查看();
    }
}

我的Global.asax文件:

 公共类MvcApplication:System.Web.HttpApplication
{
    保护无效的Application_Start()
    {
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        AreaRegistration.RegisterAllAreas();
    }
}


解决方案

重定向比路由一个独立的问题。由于您重定向目标的任何的URL到其对应的本地化是一个横切关注点最好的办法是做一个全球性的过滤器。

 公共类RedirectToUserLanguageFilter:IActionFilter
{
    私人只读字符串defaultCulture;
    私人只读的IEnumerable<串GT; supportedCultures;    公共RedirectToUserLanguageFilter(字符串defaultCulture,IEnumerable的<串GT; supportedCultures)
    {
        如果(string.IsNullOrEmpty(defaultCulture))
            抛出新的ArgumentNullException(defaultCulture);
        如果(supportedCultures == NULL ||!supportedCultures.Any())
            抛出新的ArgumentNullException(supportedCultures);        this.defaultCulture = defaultCulture;
        this.supportedCultures = supportedCultures;
    }    公共无效OnActionExecuting(ActionExecutingContext filterContext)
    {
        VAR routeValues​​ = filterContext.RequestContext.RouteData.Values​​;        //如果没有文化没有价值,重定向
        如果(routeValues​​ = NULL&放大器;!&安培;!routeValues​​.ContainsKey(文化))
        {
            串文化= this.defaultCulture;
            VAR userLanguages​​ = filterContext.HttpContext.Request.UserLanguages​​;
            如果(userLanguages​​.Length大于0)
            {
                的foreach(在userLanguages​​.SelectMany字符串语言(X => x.Split(';')))
                {
                    //检查设置之前,语言是否被支持。
                    如果(supportedCultures.Contains(语言))
                    {
                        文化=语言;
                        打破;
                    }
                }
            }            //文化添加到路由值
            routeValues​​.Add(文化,文化);            filterContext.Result =新RedirectToRouteResult(routeValues​​);
        }
    }    公共无效OnActionExecuted(ActionExecutedContext filterContext)
    {
        // 没做什么
    }
}

用法

 公共类一个FilterConfig
{
    公共静态无效RegisterGlobalFilters(GlobalFilterCollection过滤器)
    {
        filters.Add(新RedirectToUserLanguageFilter(恩,新的String [] {恩,德,FR,ES,它}));
        filters.Add(新HandleErrorAttribute());
    }
}

还请注意,您的路由配置错误。路由设置运行每个应用程序的启动一次,所以默认文化背景,以当前线程是没有意义的。事实上,你不应该在所有的,因为你希望它错过,所以如果没有文化设置你的默认航线将执行设置默认培养你的文化路线。

  routes.MapRoute(
    名称:DefaultLocalized
    网址:{文化} / {控制器} / {行动} / {ID}
    限制:新{文化= @(\\ w {2})|(\\ w {2} - \\ w {2})},
    默认:新{控制器=家,行动=索引,ID = UrlParameter.Optional}
);routes.MapRoute(
    名称:默认,
    网址:{控制器} / {行动} / {ID}
    默认:新{控制器=家,行动=索引,ID = UrlParameter.Optional}
);

I would like to be able to create a succinct language-specific default URL for my website so that when someone browses to:

somesite.com

They get redirected to a language-culture page such as:

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

Specifically, I do not want /Home/Index appended to the URLs:

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

I am committed to making this site using RouteLocalization.mvc

And I would like to use MVC Attribute Routing to the extent feasible.

I am having trouble figuring out how to cause the Start() method redirect to a language-culture specific URL without the addition of something like "index".

Samples of what I have attempted follow:

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 }
        );
    }
}

And my home controller:

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();
    }
}

My Global.asax file:

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

解决方案

Redirecting is a separate concern than routing. Since your goal of redirecting any URL to its localized counterpart is a cross-cutting concern your best bet is to make a global filter.

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
    }
}

Usage

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());
    }
}

Note also that your routing is misconfigured. The route setup is run one time per application startup, so setting the default culture to that of the current thread is meaningless. In fact, you should not be setting a default culture at all for your culture route because you want it to miss so your Default route will execute if there is no culture set.

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 }
);

这篇关于特定于语言的默认URL中使用MVC的属性路由和RouteLocalization.mvc的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆