zoukankan      html  css  js  c++  java
  • ASP.NET MVC 多语言实现——URL路由

    考虑实现一个完整的基于asp.net mvc的多语言解决方案,从路由到model再到view最后到数据库设计(先挖好坑,后面看能填多少)。

    我所见过的多语言做得最好的网站莫过于微软的msdn了,就先从模仿它的路由开始

    仅实现相同的url格式很简单,只要将默认的路由加上一个表示语言的变量就可以了

    public static void RegisterRoutes(RouteCollection routes)
            {
           //other routes
    routes.MapRoute( name: "Default", url: "{culture}/{controller}/{action}/{id}", constraints: new { culture = "zh-cn|en-us" }, defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); }

    然后就可以通过类似 /zh-cn/home/index或/en-us/home/index 的url访问相应页面。然而仅是这样肯定没什么实际性的作用,之前浏览过很多多语言站点,发现url里面有代表语言的都是基本都是以zh或zh-cn代表中文,en或en-us代表English,这一定有什么联系;C#有一个表示区域信息的class CultureInfo,通过设置线程的区域信息来调整某些内容的默认展示方式,最常见的就是日期格式的显示。culture的值可参照 http://www1.cs.columbia.edu/~lok/csharp/refdocs/System.Globalization/types/CultureInfo.html,当然一个Website没人有精力去支持所有语言,可以通过mvc的路由去限制,上面限制了仅中文简体(zh-cn)和美式英语(en-us)。mvc执行过程中与culture有关的步骤大概有Controller激活(不确定)->Action的Model绑定->Action执行->View呈现,因此只要在asp.net为一个客户端请求调用一个线程到使用该线程执行Controller Action的这段过程中加入设置culture的操作就能达到目的,我用的则是ActionFilter:

    using System;
    using System.Globalization;
    using System.Threading;
    using System.Web.Mvc;
    /************************************************************************************************************************************************
     * Class Name : InternationalizationAttribute.cs
     * Create Date: Tue, ‎Jan ‎12, ‎2016
     * Last Update: Thur, ‎Jan 12, ‎2016
     * Description: Set Culture. learn from http://stackoverflow.com/questions/1560796/set-culture-in-an-asp-net-mvc-app.
     * Author     : Cameron
     ************************************************************************************************************************************************/
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public sealed class InternationalizationAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            bool isSkipInternationalize = filterContext.ActionDescriptor.IsDefined(typeof(WithoutInternationalizationAttribute), inherit: true)
                                            || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(WithoutInternationalizationAttribute), inherit: true);
            if (!isSkipInternationalize)
            {
                string culture = (string)filterContext.RouteData.Values["culture"];
                //if (string.IsNullOrEmpty(culture))
                //{
                //    System.Web.HttpCookie cookieCulture = filterContext.HttpContext.Request.Cookies["culture"];
                //    if (cookieCulture == null)
                //        filterContext.RouteData.Values.Add("culture", "zh-cn");
                //    else
                //        filterContext.RouteData.Values.Add("culture", cookieCulture.Value);
                //    filterContext.HttpContext.Response.RedirectToRoute("Default");
                //}
                //else {
                //filterContext.RequestContext.HttpContext.User
                Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(culture);
                Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture);
                //}
            }
        }
    }
    
    /// <summary>
    /// Actions and controllers with the WithoutInternationalization attribute are skipped by the InternationalizationAttribute.
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public sealed class WithoutInternationalizationAttribute : Attribute
    {
    }

     相应controller代码:

        [Internationalization]
        public class HomeController : Controller
        {
            public ActionResult Index()
            {
                return View();
            }
    
            public ActionResult Login()
            {
                return View();
            }
    
            [HttpPost]
            public ActionResult Login(LoginViewModel loginModel)
            {
                return View();
            }
    
            [WithoutInternationalization]
            public ActionResult ChooseCulture(string culture, string returnUrl)
            {
                //string url = GetApplicationPath(HttpContext.Request) + "/aaaa/bbb?c=5";
                //var request = new HttpRequest(null, Request.Url.AbsoluteUri, "");
                //var response = new HttpResponse(new System.IO.StringWriter());
                //var httpContext = new HttpContext(request, response);
                //var routeData = System.Web.Routing.RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
                //var values = routeData.Values;
    
                //HttpCookie cookieCulture = Request.Cookies["culture"];
                //var originalCulture = RouteData.Values["culture"];
                //if (cookieCulture == null)
                //{
                //    RouteData.Values.Add("culture", "zh-cn");
                //}
                //else {
                //}
                //写得有点死,有待改进
                if (!returnUrl.EndsWith("/"))
                    returnUrl += "/";
                if (!string.IsNullOrEmpty(returnUrl) && returnUrl.Length > 3 && returnUrl.StartsWith("/") && returnUrl.IndexOf("/", 1) > 0 && new string[] { "zh-cn", "en-us" }.Contains(returnUrl.Substring(1, returnUrl.IndexOf("/", 1) - 1)))
                    returnUrl = $"/{culture}{returnUrl.Substring(returnUrl.IndexOf("/", 1))}";
                else
                    returnUrl = $"/{culture}{returnUrl}";
                return Redirect(returnUrl);
            }
        }

     Layout View 选择语言部分代码:

    @using Resources
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>@ViewBag.Title - @Resource1.my_app</title>
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
    </head>
    <body>
        <div class="navbar navbar-inverse navbar-fixed-top">
            <div class="container">
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    @Html.ActionLink(Resource1.app_name, "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
                </div>
                <div class="navbar-collapse collapse">
                    <ul class="nav navbar-nav">
                        <li>@Html.ActionLink(Resource1.home, "Index", "Home")</li>
                        <li>@Html.ActionLink("中文", "ChooseCulture", new { culture = "zh-cn", returnUrl = Request.RawUrl })</li>
                        <li>@Html.ActionLink("English", "ChooseCulture", new { culture = "en-us", returnUrl = Request.RawUrl })</li>
                    </ul>
                    <ul class="nav navbar-nav navbar-right">
                        <li>@Html.ActionLink(Resource1.Login, "Login", "Home")</li>
                    </ul>
                </div>
            </div>
        </div>
        <div class="container body-content">
            @RenderBody()
            <hr />
            <footer>
                <p>&copy; @DateTime.Now.Year - @Resource1.my_app</p>
            </footer>
        </div>
    
        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/bootstrap")
        @RenderSection("scripts", required: false)
    </body>
    </html>
    View Code

    This is my first bolg...

    附上Artech大神的另一种实现方式,http://www.cnblogs.com/artech/archive/2012/05/04/localization-via-url-routing.html

  • 相关阅读:
    IbatisNet 快速开发使用 之一
    C#开发和调用Web Service
    如何构建银行数据仓库
    SQLSREVER如何创建和使用动态游标
    一个sql语句,包含有几乎所有标准查询语法
    深入研究SQL结构化查询语言中的LIKE语句
    数据库正规化和设计技巧
    黑客攻破SQL服务器系统的十种方法
    实用的存储过程
    数据库人员手边系列:SQL Server常见连接错误
  • 原文地址:https://www.cnblogs.com/CameronWu/p/5709442.html
Copyright © 2011-2022 走看看