我正在制定一个新项目的概念,我需要支持多语言 URL。理想情况下,所有 URL 都需要使用用户的母语。所以我们不想使用domain.com/en/contact and 域名.com/es/contact但我们喜欢域名.com/contact and 域名.com/contactar(contactar 是西班牙语的联系方式)。在内部,两者应该路由到相同的接触控制器 class.
这可以通过为每种语言向 Global.asax.cs 添加多个静态路由来处理,但我们希望使其变得非常动态,并且希望系统用户能够通过内容管理更改 URL 的翻译系统。因此,我们需要某种从 URL 到控制器和操作的动态映射。
通过查看MVC3的源代码我发现进程请求初始化的方法MvcHandler负责确定要创建哪个控制器。它只是看起来在路线数据获取控制器的名称。覆盖默认 MVC 路由的一种方法是创建一个使用自定义的简单默认路由路由处理程序. This 路由处理程序强制 MVC 使用我自己的自定义子类版本MvcHandler覆盖进程请求初始化方法。这个重写的方法将我自己动态找到的控制器和操作插入到路线数据在调用回原来的之前进程请求初始化.
我试过这个:
全局.asax.cs
routes.Add(
new Route("{*url}", new MultilingualRouteHandler())
{
Defaults = new RouteValueDictionary(new { controller = "Default", action = "Default" })
}
);
多语言RouteHandler.cs
public class MultilingualRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new MultilingualMVCHandler(requestContext);
}
}
多语言 MvcHandler.cs
public class MultilingualMVCHandler : MvcHandler
{
public MultilingualMVCHandler(RequestContext context) : base(context)
{
}
protected override void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
if (RequestContext.RouteData.Values.ContainsKey("controller"))
{
RequestContext.RouteData.Values.Remove("controller");
}
if (RequestContext.RouteData.Values.ContainsKey("action"))
{
RequestContext.RouteData.Values.Remove("action");
}
RequestContext.RouteData.Values.Add("controller", "Product");
RequestContext.RouteData.Values.Add("action", "Index");
base.ProcessRequestInit(httpContext, out controller, out factory);
}
}
在此处理程序中,出于测试目的,我将控制器和操作硬编码为一些固定值,但使其动态化并不困难。它可以工作,但唯一的问题是我必须修改 ASP.NET MVC3 的源代码才能使其工作。问题是进程请求初始化的方法MvcHandler是私有的,因此不能被覆盖。我修改了源代码并将其更改为受保护的虚拟,这允许我覆盖它。
这一切都很好,但可能不是最好的解决方案。我总是需要分发我自己的 System.Web.Mvc.dll 版本,这很麻烦。如果能配合 RTM 版本使用就更好了。
我是否错过了挂钩 ASP.NET MVC 的任何其他可能性,这些可能性允许我根据 URL 动态确定要启动的控制器和操作?我想到的另一种方法是构建路由集合动态地在 *Application_Start* 上进行,但我认为这将使动态更改它变得更加困难。
如果我还没有找到任何有关钩子的提示,我将不胜感激。