如何在全球范围内改变路线? [英] How to change routes globally?

查看:108
本文介绍了如何在全球范围内改变路线?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想两种语言之间进行切换我的意见,MVC 3 - PL和EN。我创建了一个视图 - EN和PL两个文件夹。因此点击任何站点适当的语言链接后,我想我的路由变化:

  routes.MapRoute(
                PL,//路线名称
                {控制器} / {行动} / {ID},// URL与参数
                新{控制器=PL,行动=索引,ID = UrlParameter.Optional} //参数的默认值
            );
 

  routes.MapRoute(
                恩,//路线名称
                {控制器} / {行动} / {ID},// URL与参数
                新{控制器=EN,行动=索引,ID = UrlParameter.Optional} //参数的默认值
            );
 

当我点击相应的链接(语言切换),它改变的CultureInfo这是永久性的所有线程。 _layout查看与切换器:

 < UL>
    <李> @ Html.ActionLink(恩,ChangeCulture,空,新{LANG =EN},空)LT; /李>
    <李> @ Html.ActionLink(PL,ChangeCulture,空,新{LANG =PL},空)LT; /李>
< / UL>
 

和控制器(也设置静态变量,郎咸平认为可以看出,在每个控制器的方法,并持之以恒请求之间):

 公众的ActionResult ChangeCulture(字符串郎)
    {

        PLController.lang =浪;
        CultureSettings setCulture =新CultureSettings();
        setCulture.InitializeCulture(郎);
        cookie.Value = CultureInfo.CurrentCulture.Name;
        this.ControllerContext.HttpContext.Response.Cookies.Add(饼干);
        返回查看(「指数」);
    }
 

InitializeCulture方法是从Page类重写如下:

 公共类CultureSettings:第{

    公共无效InitializeCulture(字符串文化)
    {
            字符串selectedLanguage;
            如果(文化== NULL)
            {
                selectedLanguage =复;
            }
            其他
            {
                selectedLanguage =文化;
            }

            的UICulture = selectedLanguage;
            文化= selectedLanguage;

            Thread.CurrentThread.CurrentCulture =
                CultureInfo.CreateSpecificCulture(selectedLanguage);
            Thread.CurrentThread.CurrentUICulture =新
                的CultureInfo(selectedLanguage);

        base.InitializeCulture();
    }
}
 

它正确地设置的CultureInfo。现在我想(根据目前的CultureInfo)为每一个导航链接并更改航线,从mysite.com/PL/{controller}/{action模式}来mysite.com/EN/{controller}/{action}.

有没有人有任何意见或可能更好的方法对这个问题?但条件是,地址必须是这样看mysite.com/EN或mysite.com/PL - 没有什么不同(即en.mysite.com)

解决方案

这是你必须决定是哪里来存储当前用户的语言的第一件事。有不同的可能:

  • 在每个URL的一部分
  • 饼干
  • 会话

恕我直言,搜索引擎优化的目的,最好把它作为URL的一部分。

因此​​,我建议编写自定义路径,这将解析从URL中的语言,并设置当前线程的文化:

 公共类LocalizedRoute:路线
{
    公共LocalizedRoute()
        : 基础(
            {语言} / {控制器} / {行动} / {ID},
            新RouteValueDictionary(新
            {
                LANG =EN-US
                控制器=家,
                行动=指数,
                ID = UrlParameter.Optional
            }),
            新RouteValueDictionary(新
            {
                LANG = @[A-Z] {2}  -  [A-Z] {2}
            }),
            新MvcRouteHandler()
        )
    {
    }

    公众覆盖的RouteData GetRouteData(HttpContextBase的HttpContext)
    {
        VAR RD = base.GetRouteData(HttpContext的);
        如果(RD == NULL)
        {
            返回null;
        }

        VAR LANG = rd.Values​​ [郎]作为串;
        如果(string.IsNullOrEmpty(郎))
        {
            //选择一个默认的文化
            LANG =EN-US;
        }

        VAR文化=新的CultureInfo(郎);

        Thread.CurrentThread.CurrentCulture =文化;
        Thread.CurrentThread.CurrentUICulture =文化;

        返回次;
    }
}
 

我们现在可以注册这个自定义路由的Global.asax

 公共静态无效的RegisterRoutes(RouteCollection路由)
{
    routes.IgnoreRoute({}资源个.axd / {* PATHINFO});

    routes.Add(默认,新LocalizedRoute());
}
 

好了,现在我们有一个模型:

 公共类MyViewModel
{
    [DisplayFormat(DataFormatString ={0:D})]
    公开日期时间日期{获得;组; }
}
 

一个控制器:

 公共类的HomeController:控制器
{
    公众的ActionResult指数()
    {
        返回查看(新MyViewModel
        {
            日期= DateTime.Now
        });
    }

    公众的ActionResult测试()
    {
        返回内容(DateTime.Now.ToLongDateString());
    }
}
 

和一个观点:

  @model MyViewModel

@ Html.DisplayFor(X => x.Date)

< UL>
    <李> @ Html.ActionLink(切换到FR-FR,指数,新{LANG =FR-FR})< /李>
    <李> @ Html.ActionLink(开关用来-DE,指数,新{LANG =去-DE})< /李>
    <李> @ Html.ActionLink(切换到EN-US,指数,新{LANG =EN-US})< /李>
< / UL>

@ Html.ActionLink(测试文化,测试)
 

现在,当你点击我们正在改变的语言,这种语言现在是路线的一部分的链接。请注意,一旦你选择了这种语言正在坚持为测试路由的语言链接。

在Scott Hanselman还写了<一href="http://www.hanselman.com/blog/GlobalizationInternationalizationAndLocalizationInASPNETMVC3JavaScriptAndJQueryPart1.aspx">nice博客文章本地化和全球化在ASP.NET这是值得一试。

I want to switch my views in MVC 3 between two languages - PL and EN. I've created two folders in Views- EN and PL. So after clicking appropriate language link at any site I want my route change from:

routes.MapRoute(
                "pl", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "PL", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

to:

routes.MapRoute(
                "en", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "EN", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

When I click appropriate link (language switcher) it changes CultureInfo which is persistent to all threads. _Layout View with switcher:

<ul>
    <li>@Html.ActionLink("En", "ChangeCulture", null, new { lang = "en"}, null)</li>
    <li>@Html.ActionLink("Pl", "ChangeCulture", null, new { lang = "pl"}, null)</li>
</ul>

and controller (which sets also static variable lang that can be seen in every controller's method and be persistent between requests):

public ActionResult ChangeCulture(string lang)
    {

        PLController.lang = lang;
        CultureSettings setCulture = new CultureSettings();
        setCulture.InitializeCulture(lang);
        cookie.Value = CultureInfo.CurrentCulture.Name;
        this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
        return View("Index");
    }

InitializeCulture method is overriden from Page class as follows:

public class CultureSettings : Page{

    public void InitializeCulture(string culture)
    {
            String selectedLanguage;
            if(culture == null)
            {
                selectedLanguage = "pl";
            }
            else
            {
                selectedLanguage = culture;
            }

            UICulture = selectedLanguage;
            Culture = selectedLanguage;

            Thread.CurrentThread.CurrentCulture =
                CultureInfo.CreateSpecificCulture(selectedLanguage);
            Thread.CurrentThread.CurrentUICulture = new
                CultureInfo(selectedLanguage);

        base.InitializeCulture();
    }
}

It sets CultureInfo properly. Now I want (according to current CultureInfo) switch routes for every navigation links and change route pattern from mysite.com/PL/{controller}/{action} to mysite.com/EN/{controller}/{action}.

Does anyone has any ideas or maybe better approach for this problem? But condition is that address must be looking like this mysite.com/EN or mysite.com/PL - not different (i.e. en.mysite.com)

解决方案

The first thing that you must decide is where to store the current user language. There are different possibilities:

  • part of every url
  • cookie
  • session

IMHO for SEO purposes it's best to have it as part of the url.

So I would recommend writing a custom route which will parse the language from the url and set the current thread culture:

public class LocalizedRoute : Route
{
    public LocalizedRoute()
        : base(
            "{lang}/{controller}/{action}/{id}",
            new RouteValueDictionary(new
            {
                lang = "en-US",
                controller = "home",
                action = "index",
                id = UrlParameter.Optional
            }),
            new RouteValueDictionary(new
            {
                lang = @"[a-z]{2}-[a-z]{2}"
            }),
            new MvcRouteHandler()
        )
    {
    }

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var rd = base.GetRouteData(httpContext);
        if (rd == null)
        {
            return null;
        }

        var lang = rd.Values["lang"] as string;
        if (string.IsNullOrEmpty(lang))
        {
            // pick a default culture
            lang = "en-US";
        }

        var culture = new CultureInfo(lang);

        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = culture;

        return rd;
    }
}

We could now register this custom route in Global.asax:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.Add("Default", new LocalizedRoute());
}

Alright, now let's have a model:

public class MyViewModel
{
    [DisplayFormat(DataFormatString = "{0:d}")]
    public DateTime Date { get; set; }
}

A controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel
        {
            Date = DateTime.Now
        });
    }

    public ActionResult Test()
    {
        return Content(DateTime.Now.ToLongDateString());
    }
}

And a view:

@model MyViewModel

@Html.DisplayFor(x => x.Date)

<ul>
    <li>@Html.ActionLink("switch to fr-FR", "index", new { lang = "fr-FR" })</li>
    <li>@Html.ActionLink("switch to de-DE", "index", new { lang = "de-DE" })</li>
    <li>@Html.ActionLink("switch to en-US", "index", new { lang = "en-US" })</li>
</ul>

@Html.ActionLink("Test culture", "test")

Now when you click on the links we are changing the language and this language is now part of the routes. Notice how once you have chosen the language this language is being persisted in the routes for the test link.

Scott Hanselman also wrote a nice blog post on localization and globalization in ASP.NET that's worth checking out.

这篇关于如何在全球范围内改变路线?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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