在ASP.NET MVC中通过URL路由实现对多语言的支持

对于一个需要支持多语言的Web应用,一个很常见的使用方式就是通过请求地址来控制界面呈现所基于的语言文化,比如我们在表示请求地址的URL中将上语言文化代码(比如en或者en-US)来指导服务器应该采用怎样的语言来显示界面的内容。对于一个ASP.NET MVC应用来说,我们很容易通过URL路由来实现这样一个功能。[本文已经同步到《How ASP.NET MVC Works?》中]

在具体介绍实现之前,我们通过一个简单的例子谈谈最终实现的效果。在通过ASP.NET MVC项目模板创建的空Web应用中,我们创建了如下一个HomeController,默认的Action方法Index用于呈现一个登录View。作为Model的LoginInfo类包含UserName和Password两个属性,分别表示登录输入的用户名和密码。需要注意的是,在两个属性上应用了DisplayAttribute并通过资源的方式指定了显示名称以实现对多语言的支持。[原代码从这里下载]

   1: public class HomeController : Controller
   2: {
   3:     public ActionResult Index()
   4:     {
   5:         return View(new LoginInfo());
   6:     }
   7: }
   8:  
   9: public class LoginInfo
  10: {
  11:     [Display(Name ="UserName", ResourceType = typeof(Resources))]
  12:     public string UserName { get; set; }
  13:  
  14:     [Display(Name="Password", ResourceType = typeof(Resources))]
  15:     [DataType(DataType.Password)]
  16:     public string Password { get; set; }
  17: }

如下所示的Action方法Index对应的View的定义,这是一个基于LogInfo的强类型View。

   1: @model MvcApp.Models.LoginInfo
   2: @using (Html.BeginForm())
   3: { 
   4:     @Html.EditorForModel()
   5:     <input type="submit" value="@MvcApp.Properties.Resources.Login" />
   6:     <input type="button" value="@MvcApp.Properties.Resources.Cancel" />
   7: }

在Global.asax中,我们修改了默认添加的URL路由注册代码,使请求URL中包含相应的语言文化信息({culture})。

   1: public class MvcApplication : System.Web.HttpApplication
   2: {
   3:     //其他成员
   4:     public static void RegisterRoutes(RouteCollection routes)
   5:     {
   6:          //其他操作
   7:         routes.MapRoute(
   8:             name: "Default",
   9:             url: "{culture}/{controller}/{action}/{id}",
  10:             defaults: new { culture="en", controller = "Home", action = "Index", id = UrlParameter.Optional }
  11:         );
  12:     }
  13: }

我们直接运行该程序,并在请求地址中指定不同的Culture(en和zh),界面呈现基于的语言正是我们期望的。

实际上针对URL路由的本地化可以通过具有如下定义的名为CultureAwareHttpModule的自定义HttpModule来实现。我们通过CultureAwareHttpModule注册了HttpApplication的BeginRequest和EndRequest事件,通过URL路由系统得到表示语言文化的路由变量culture,并对当前线程的Culture和UICulture进行了相应的设置和恢复。

   1: public class CultureAwareHttpModule : IHttpModule
   2: {
   3:     private CultureInfo currentCulture;
   4:     private CultureInfo currentUICulture;
   5:  
   6:     public void Dispose(){}
   7:     public void Init(HttpApplication context)
   8:     {
   9:         context.BeginRequest += SetCurrentCulture;
  10:         context.EndRequest   += RecoverCulture;
  11:     }
  12:     private  void SetCurrentCulture(object sender, EventArgs args)
  13:     {
  14:         currentCulture   = Thread.CurrentThread.CurrentCulture;
  15:         currentUICulture = Thread.CurrentThread.CurrentUICulture;
  16:         HttpContextBase contextWrapper = new HttpContextWrapper(HttpContext.Current);
  17:         RouteData routeData = RouteTable.Routes.GetRouteData(contextWrapper);
  18:         object culture;
  19:         if (routeData.Values.TryGetValue("culture", out culture))
  20:         {
  21:  
  22:             try
  23:             {
  24:                 Thread.CurrentThread.CurrentCulture   = new CultureInfo(culture.ToString());
  25:                 Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture.ToString());
  26:             }
  27:             catch
  28:             { }
  29:         }
  30:     }
  31:     private void RecoverCulture(object sender, EventArgs args)
  32:     {
  33:         Thread.CurrentThread.CurrentCulture   = currentCulture;
  34:         Thread.CurrentThread.CurrentUICulture = currentUICulture;
  35:     }
  36: }

我们只需要通过如下配置对CultureAwareHttpModule进行注册即可。

   1: <configuration>
   2:   <system.web>
   3:     <httpModules>
   4:       <add name="CultureAwareHttpModule" type="MvcApp.CultureAwareHttpModule, MvcApp"/>
   5:     </httpModules>
   6:     ...
   7: </configuration>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏有趣的django

Django rest framework(7)----分页

第一种分页  PageNumberPagination 基本使用 (1)urls.py urlpatterns = [ re_path('(?P<ve...

6297
来自专栏ASP.NET MVC5 后台权限管理系统

ASP.NET MVC5+EF6+EasyUI 后台管理系统(30)-本地化(多语言)

我们的系统有时要扩展到其他国家,或者地区,需要更多的语言环境,微软提供了一些解决方案,原始我们是用js来控制的,现在不需要了。 我们只要创建简单的资源文件,通过...

3327
来自专栏技术博客

菜菜从零学习WCF九(会话、实例化和并发)

在服务协定上设置System.ServiceModel.ServiceContractAttribute.SessionMode值

1003
来自专栏开发 & 算法杂谈

Hiredis源码阅读(二)

上一篇介绍了Hiredis中的同步api以及回复解析api,这里紧接着介绍异步api。异步api需要与事件库(libevent、libev、ae一起工作)。

4175
来自专栏林德熙的博客

WPF 如何在绑定失败异常

在开发 WPF 程序,虽然 xaml 很好用,但是经常会出现小伙伴把绑定写错了。因为默认的 VisualStudio 是没有自动提示,这时很容易复制粘贴写出一个...

2571
来自专栏Phoenix的Android之旅

JSONObject 和 JsonObject 的区别

做Java开发经常要用Json来做数据的格式化解析,虽然在Android平台上我们习惯的使用 JSONObject, 但不知道你有没有这样的疑问,我们在impo...

2221
来自专栏linjinhe的专栏

LevelDB:使用介绍

Get 接口和 Put 接口比较像,除了 leveldb::ReadOptions 参数是用来控制读操作的,具体见链接指向的代码。

7055
来自专栏LinkedBear的个人空间

HttpClient入门及其应用 顶

这些需求可能或多或少的会发生在平时的开发中,针对每种情况,可能解决方案不止一种。本文将会使用HttpClient这种工具来讲解HttpClient的相关知识,以...

1321
来自专栏圣杰的专栏

.Net异步编程知多少

1. 引言 最近在学习Abp框架,发现Abp框架的很多Api都提供了同步异步两种写法。异步编程说起来,大家可能都会说异步编程性能好。但好在哪里,引入了什么问题,...

2297
来自专栏大内老A

WCF版的PetShop之三:实现分布式的Membership和上下文传递

通过上一篇了解了模块内基本的层次划分之后,接下来我们来聊聊PetShop中一些基本基础功能的实现,以及一些设计、架构上的应用如何同WCF进行集成。本篇讨论两个问...

2585

扫码关注云+社区

领取腾讯云代金券