gpt4 book ai didi

asp.net-mvc - 使用 ASP.NET MVC 的多语言 URL

转载 作者:行者123 更新时间:2023-12-02 07:11:32 25 4
gpt4 key购买 nike

我正在制定一个新项目的概念,我需要支持多语言 URL。理想情况下,所有 URL 都需要使用用户的母语。因此,我们不想使用 domain.com/en/contactdomain.com/es/contact,但我们喜欢 domain.com/contact strong> 和 domain.com/contactar(contactar 是西类牙语的“联系人”)。在内部,两者都应该路由到同一个 ContactController 类。

这可以通过为每种语言向 Global.asax.cs 添加多个静态路由来处理,但我们希望使其变得非常动态,并且希望系统用户能够通过以下方式更改 URL 的翻译内容管理系统。因此,我们需要某种从 URL 到 Controller 和操作的动态映射。

通过查看 MVC3 的源代码,我发现 MvcHandlerProcessRequestInit 方法负责确定要创建哪个 Controller 。它只是在RouteData中查找来获取 Controller 的名称。覆盖默认 MVC 路由的一种方法是创建一个使用自定义 RouteHandler 的简单默认路由。此 RouteHandler 强制 MVC 使用我自己的自定义子类版本的 MvcHandler 来重写 ProcessRequestInit 方法。此重写方法在回调到原始 ProcessRequestInit 之前,将我自己动态找到的 Controller 和操作插入到 RouteData 中。

我试过这个:

Global.asax.cs

routes.Add(
new Route("{*url}", new MultilingualRouteHandler())
{
Defaults = new RouteValueDictionary(new { controller = "Default", action = "Default" })
}
);

MultilingualRouteHandler.cs

public class MultilingualRouteHandler : IRouteHandler
{

public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new MultilingualMVCHandler(requestContext);
}

}

MultilingualMvcHandler.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);

}

}

在此处理程序中,出于测试目的,我将 Controller 和操作硬编码为一些固定值,但使其动态化并不困难。它可以工作,但唯一的问题是我必须修改 ASP.NET MVC3 的源代码才能使其工作。问题是 MvcHandlerProcessRequestInit 方法是私有(private)的,因此无法重写。我修改了源代码并将其更改为 protected 虚拟,这允许我覆盖它。

这一切都很好,但可能不是最好的解决方案。我总是需要分发我自己的 System.Web.Mvc.dll 版本,这很麻烦。如果能配合 RTM 版本就更好了。

我是否错过了 Hook ASP.NET MVC 的任何其他可能性,这些可能性允许我根据 URL 动态确定要启动的 Controller 和操作?我想到的另一种方法是在 *Application_Start* 上动态构建 RouteCollection,但我认为这会使动态更改它变得更加困难。

如果有任何我还没有找到的钩子(Hook)技巧,我将不胜感激。

最佳答案

现在已经相当老了,以防万一其他人正在寻找类似的东西......

除非我完全误解了你想要做什么,否则它真的很简单。

第 1 步:向 global.ascx.cs 添加一条新路由,其中​​包含对您的个人路由引擎的引用

routes.Add(new MyProject.Routing.ContentRoutingEngine());

确保它位于路由列表中的正确位置,以便其他路由引擎可以在需要时捕获它之前的内容,或者如果您的引擎不处理特定路由,则继续路由搜索。我把它放在忽略之后,但在 MVC 默认路由之前。

第 2 步:创建内容路由引擎,确保它继承自 System.Web.Routing.RouteBase 抽象类,并根据需要重写 GetRouteData 和 GetVirtualPath 方法,例如

public class ContentRoutingEngine : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var routeHandler = new MvcRouteHandler();
var currentRoute = new Route("{controller}/{action}", routeHandler);
var routeData = new RouteData(currentRoute, routeHandler);

// set your values dynamically here
routeData.Values["controller"] = "Home" ;
// or
routeData.Values.Add("action", "Index");

// return the route, or null to have it passed to the next routing engine in the list
return routeData;
}

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
//implement this to return url's for routes, or null to just pass it on
return null;
}
}

这样就可以了。您可以在引擎中根据需要动态更改路由,而无需更改 MVC 源。让标准 MVC RouteHandler 实际调用 Controller 。

后记:显然上面的代码不是生产标准 - 编写它是为了让发生的事情尽可能明显。

关于asp.net-mvc - 使用 ASP.NET MVC 的多语言 URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4874061/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com