asp.net - 使用 MVC 的属性路由和 RouteLocalization.mvc 的特定于语言的默认 URL

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

我希望能够为我的网站创建一个简洁的特定于语言的默认 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 制作这个网站
  • Dresel/RouteLocalization
  • Translating Your ASP.NET MVC Routes

  • 我想在可行的范围内使用 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 }
            );
        }
    }
    

    还有我的家庭 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();
        }
    }
    

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

    最佳答案

    重定向是一个与路由不同的问题。由于您将任何 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 }
    );
    

    关于asp.net - 使用 MVC 的属性路由和 RouteLocalization.mvc 的特定于语言的默认 URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37239919/

    相关文章:

    asp.net - 依赖注入(inject)和存储库模式之间的区别

    c# - Mono MVC5 - View 不起作用

    c# - mvc c# 中的安全 id 值

    c# - 在服务器应用程序中使用 threadPool 或 new thread() 进行多线程

    c# - 如何使用 EF 在我的 asp.net core 3.1 MVC 应用程序中正确使用我的 SQLite db?

    C#/ASP.NET 遍历表

    ASP.NET MVC 3 成员(member)提供程序

    c# - 数据库优先和区域

    asp.net-mvc-4 - Mvc4 在一个 View 中有 2 种形式

    c# - 从网络应用程序调用所需的最低用户权限?