建站学 - 轻松建站从此开始!

建站学-个人建站指南,网页制作,网站设计,网站制作教程

当前位置: 建站学 > 网站开发 > asp.net教程 >

ASP.NET MVC的全球化方案(2)

时间:2010-10-20 22:20来源: 作者: 点击:
这里要注意几点: 1.routes.IgnoreRoute({resource}.axd/{*pathInfo});会在路由表中添加一条IgnoreRouteInternal类型的路由,只不过这条是需要被跳过的而已。三个类的关系是: RouteBase-Route-IgnoreRouteInternal
这里要注意几点:

1.routes.IgnoreRoute("{resource}.axd/{*pathInfo}");会在路由表中添加一条IgnoreRouteInternal类型的路由,只不过这条是需要被跳过的而已。三个类的关系是:

RouteBase->Route->IgnoreRouteInternal

而不巧的是IgnoreRouteInternal是个私有类,因此,只能借助反射了。

2.为路由设置Constraints属性时,实际上是为其指定一个IRouteConstraint。MVC内部有一个实现了IRouteConstraint的接受正则表达式的类,我们在MapRoute方法中用一个string初始化Constraints,实际上就是实例化了这个类。而这里我们的需求显然要复杂点:需要判断ci参数是否是支持的,所以也就有了CulturePrefixRule实现IRouteConstraint。

3.带有ci参数的路由更“特殊”,所以最好还是放在路由表前面。原因我就不再累述了。

  

在Controller的Action执行前跳转

所有的Controller都应该具有一个相同的行为:能够针对没有ci参数的url实施跳转。因此自然想到实现一个基类Controller,这里我命名为BaseController,代码如下:

01 public class BaseController : Controller
02 {
03     protected string redirectUrl;
04   
05     protected override void Initialize(System.Web.Routing.RequestContext requestContext)
06     {
07         base.Initialize(requestContext);
08         object cultureValue;
09         //检测ci参数
10         if (requestContext.RouteData.Values.TryGetValue("ci", out cultureValue))
11         {
12             //设置当前线程的culture
13             try
14             {
15                 Thread.CurrentThread.CurrentUICulture = CultureProvider.GetCultureInfo(cultureValue.ToString());
16                 Thread.CurrentThread.CurrentCulture = CultureProvider.GetCultureInfo(cultureValue.ToString());
01                 Response.Cookies.Add(new HttpCookie(CultureProvider.culturecookiekey,cultureValue.ToString()));
02             }
03             catch { throw new Exception("Culture Error!"); }
04         }
05         else //如果没有ci参数
06         {
07             //check cookie
08             HttpCookie cLang = requestContext.HttpContext.Request.Cookies[CultureProvider.culturecookiekey];
09             if (cLang != null)
10             {
11                 cultureValue = cLang.Value;
12             }
13             else //check brower setting
14             {
15                 string[] langs = requestContext.HttpContext.Request.UserLanguages;
16                 if (langs != null && langs.Length > 0)
17                 {
18                     cultureValue = langs[0].Split(';').First();
19                 }
20             }
21   
22             if (cultureValue == null)
23             {
24                 cultureValue = CultureProvider.culturedefault;
25             }
26             //设置redirectUrl,如果不需要重定向到化redirectUrl 为null
27             redirectUrl = string.Format(@"/{0}{1}",
28                 cultureValue.ToString(),
29                 requestContext.HttpContext.Request.RawUrl);
30   
31         }
32     }
33   
34     protected override IActionInvoker CreateActionInvoker()
35     {
36         return new CustomControllerActionInvoker(redirectUrl);
37     }
38 }
39   
40 //一个IActionInvoker 的实现,MVC默认使用ControllerActionInvoker,因为在
41 //redirectUrl != null 的时候需要在action执行之前执行重定向
42 internal class CustomControllerActionInvoker : ControllerActionInvoker
43 {
44     string redirectUrl;
45     public CustomControllerActionInvoker(string url)
46         : base()
47     {
48         redirectUrl = url;
49     }
50     protected override ActionResult InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
51     {
52         object returnValue;
53        //ChildAction内部不能重定向
54         if (!string.IsNullOrEmpty(redirectUrl) && !controllerContext.IsChildAction)
55             returnValue = new RedirectResult(redirectUrl);
56         else
57             returnValue = actionDescriptor.Execute(controllerContext, parameters);
58         ActionResult result = CreateActionResult(controllerContext, actionDescriptor, returnValue);
59         return result;
60     }
61 }
62   
63 public static class CultureProvider
64 {
65     public const string culturecookiekey = "Lang";
66     public const string culturedefault = "en-US";
67   
68     public static CultureInfo GetCultureInfo(string ci)
69     {
70         try
71         {
72             return new CultureInfo(ci);
73         }
74         catch
75         {
76             return null;
77         }
78     }
79 }

只要所有的Controller继承这个BaseController即可。

这里需要重点指出的是CustomControllerActionInvoker类,事实上发现从这个类入手解决重定向问题花了我不少时间,为此我不得不调试MVC的源码。当然最初的想法是在每个action执行时手动判断redirectUrl,从而指导重定向,但显然,没人愿意将自己已经写好的action都拿出来一个个改,所以也就有了这个小小的探索。

 

页面中的链接、跳转

最后令我感到即高兴又担心的问题是:当我使用这个框架后,页面中的所有链接和跳转因素几乎都能自动在url前面加上ci参数!虽然我知道类似Html.ActionLink之类的helper有从路由表中产生url的能力,但是能够自动添加上ci,还是让我感到有点始料未及。不过,链接的url是否正确,还是要注意,有一些特殊情况。

 

页面中使用资源

在页面中引用资源可以直接在C#脚本中引用Resource类。这里提供一个helper。这个Html的扩展方法。

01 public static class ResourceExtensions
02 {
03     public static string Resource(this Controller controller, string expression, params object[] args)
04     {
05         ResourceExpressionFields fields = GetResourceFields(expression, "~/");
06         return GetGlobalResource(fields, args);
07     }
08  
09     public static string Resource(this HtmlHelper htmlHelper, string expression, params object[] args)
10     {
11         string path = "~/";
12         ResourceExpressionFields fields = GetResourceFields(string.Format("Resource,{0}", expression), path);
13         return GetGlobalResource(fields, args);
14     }
15  
16     static string GetGlobalResource(ResourceExpressionFields fields, object[] args)
17     {
18         return string.Format((string)HttpContext.GetGlobalResourceObject(fields.ClassKey, fields.ResourceKey, CultureInfo.CurrentUICulture), args);
19     }
20  
21     static ResourceExpressionFields GetResourceFields(string expression, string virtualPath)
22     {
23         var context = new ExpressionBuilderContext(virtualPath);
24         var builder = new ResourceExpressionBuilder();
25         return (ResourceExpressionFields)builder.ParseExpression(expression, typeof(string), context);
26     }
27 }

需要注意的是这个方法默认认为Resource是资源的类名,所以必要的话需要修改

ResourceExpressionFields fields = GetResourceFields(string.Format("Resource,{0}", expression), path); 中的"Resource,{0}"

 

 

结语

 

初学MVC,甚至可以说是初学web开发。以上是我个人提出的一种方案,不知道有没有什么不足之处,还请各位看官提出见解,探讨一下。

点击下载例子

其他相关资源:

http://blog.miniasp.com/post/2010/01/ASPNET-MVC-Developer-Note-Part-15-Globalization-and-Localization.aspx

(责任编辑:admin)
织梦二维码生成器
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片