考虑实现一个完整的基于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 > && returnUrl.StartsWith("/") && returnUrl.IndexOf("/", ) > && new string[] { "zh-cn", "en-us" }.Contains(returnUrl.Substring(, returnUrl.IndexOf("/", ) - )))
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>

This is my first bolg...

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

ASP.NET MVC 多语言实现——URL路由的更多相关文章

  1. 跟我学ASP.NET MVC之十一:URL路由

    摘要: 在MVC框架之前,ASP.NET假定在请求的URLs和服务器硬盘文件之间有直接的关系.服务器的职责是接收浏览器请求,从相应的文件发送输出. 这种方法只能工作于Web表单,每一个ASPX页面既是 ...

  2. EF+LINQ事物处理 C# 使用NLog记录日志入门操作 ASP.NET MVC多语言 仿微软网站效果(转) 详解C#特性和反射(一) c# API接受图片文件以Base64格式上传图片 .NET读取json数据并绑定到对象

    EF+LINQ事物处理   在使用EF的情况下,怎么进行事务的处理,来减少数据操作时的失误,比如重复插入数据等等这些问题,这都是经常会遇到的一些问题 但是如果是我有多个站点,然后存在同类型的角色去操作 ...

  3. ASP.NET MVC的运行机制--url的全局分析

    全局 首先我们来看一副图片       首先,用户通过Web浏览器向服务器发送一条url请求,这里请求的url不再是xxx.aspx格式,而是http://HostName/ControllerNam ...

  4. ASP.NET MVC 及 Areas 简单控制路由

    ASP.NET MVC中怎么去控制路由,这个想关的文章很多,我在这里就是自我总结一下,仅供参考. 1.我们新建一个项目,查看RouteConfig.cs,代码如下: public static voi ...

  5. 在ASP.NET MVC中实现基于URL的权限控制

    本示例演示了在ASP.NET MVC中进行基于URL的权限控制,由于是基于URL进行控制的,所以只能精确到页.这种权限控制的优点是可以在已有的项目上改动极少的代码来增加权限控制功能,和项目本身的耦合度 ...

  6. ASP.NET MVC 5 入门教程 (3) 路由route

    文章来源: Slark.NET-博客园 http://www.cnblogs.com/slark/p/mvc-5-get-started-route.html 上一节:ASP.NET MVC 5 入门 ...

  7. ASP.NET 4的Demo实践:URL路由改进支持

    从.NET框架3.5 SP1开始,微软推出了ASP.NET路由支持,从而实现了特定资源的URL与其对应的Web服务器上的物理文件之间的彻底解耦.借助于ASP.NET路由支持,开发人员可以定义一组路由规 ...

  8. 8.MVC框架开发(URL路由配置和URL路由传参空值处理)

    1.ASP.NET和MVC的路由请求处理 1)ASP.NET的处理 请求---------响应请求(HttpModule)--------处理请求(HttpHandler)--------把请求的资源 ...

  9. ASP.NET MVC5(一)—— URL路由

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

随机推荐

  1. php编译安装报错:make: *** [sapi/cli/php] Error 1 解决办法

    ext/iconv/.libs/iconv.o: In function `php_iconv_stream_filter_ctor':/ext/iconv/iconv.c:2491: undefin ...

  2. 学习日志 - Openwrt安装python然后wallproxy

    前提: - 先要把U盘插入路由器的usb口,大多数情况Openwrt都会自动挂载的吧,尽量找当前年或前一年的固件.ssh进路由器,可以看到/mnt/sda1 -  让路由器联网,因为需要从网络上下载安 ...

  3. easyUI + swfupload 多附件上传功能

    public void UPLOADFILED() { Date dt = new Date(System.currentTimeMillis()); SimpleDateFormat sdf = n ...

  4. 关于Markdown

    之前有接触过一点markdown,知道能生成好看的排版,只是太懒都不去看不去记那些标签 现在才发现它简单好用得有点伟大 一个在线的Markdown编辑器:https://stackedit.io/ed ...

  5. Excel通过身份证获取出生年月,性别,年龄,生肖,星座,省份等信息总结归纳

    Excel通过身份证获取出生年月,性别,年龄,生肖,星座,省份等信息总结归纳 早期的身份证号码为15位数字,现在使用的身份证号码为18位数字,它们的含义如下:(1)15位:1-6位为地区代码,7-8位 ...

  6. 荒废了很久的java以及微信公众平台今天拿起来看了看:这里有很好的教程

    我的微信公众号刚刚起步: ,感兴趣可以关注一下. 关于java开发微信公众号有一个很好的教程博客:推荐一下:http://blog.csdn.net/lyq8479/article/details/8 ...

  7. Django中的QuerySet查询优化之select_related

    在数据库有外键的时候,使用 select_related() 和 prefetch_related() 可以很好的减少数据库请求的次数,从而提高性能.本文通过一个简单的例子详解这两个函数的作用.虽然Q ...

  8. My first blog in cnblog

    Learning, record and shareing. Being stronger.

  9. 一个简单的物料防错DEMO

    前言 快2个月没写过博客了,就算是记流水账似的文章都没时间写,主要是太忙了:太多的bug要修复.太多由于bug引起的异常问题要解决.还有新的项目要开发,不忙怎么行呢?最近利用业余时间在鼓捣一个PDA的 ...

  10. Spring MVC简介

    Spring MVC简介 Spring MVC框架是有一个MVC框架,通过实现Model-View-Controller模式来很好地将数据.业务与展现进行分离.从这样一个角度来说,Spring MVC ...