如何在MVC选择路由之前添加路由参数

Dra*_*nov 7 asp.net-mvc localization internationalization asp.net-mvc-routing asp.net-mvc-3

我正在尝试为现有的MVC 3应用程序添加对不同语言的支持.到目前为止,我的链接是

oldUrl -> myapp.com/Item/Details/5/some-title
Run Code Online (Sandbox Code Playgroud)

网站上有不同地方的网站链接.但是现在我想更改URL以便包含语言:

newUrl -> kmyapp.com/en/Item/Details/5/some-title
Run Code Online (Sandbox Code Playgroud)

但是我希望oldUrl链接有效.问题是如何做到这一点...最简单的方法是添加另一条路线,但我已经有太多它们而且它变得有点丑陋,当我从一个不创建的网页创建网址时有语言链接也没有语言所以我必须做其他事情.

另一种方法是覆盖在MVC尝试将请求映射到特定路由之前的某些东西,但是已经解析了请求URL并填充了routeValues字典.所以我可以检查语言,如果它没有包含在路由参数中,我可以自己添加它并调用父类的实现继续.那可能吗?我应该注意什么 - UrlRoutingModule,MvcHttpHandler或其他什么?我可以覆盖什么以及如何告诉MVC使用我的版本?

任何其他想法也将不胜感激!

Rob*_*nik 11

当然有很多解决方案.我要告诉你两个:

  • 您在应用程序中控制的一个
  • 您在应用程序之外控制的一个(在IIS上)

解决方案一 - Asp.net MVC路由

提供涵盖路由和新路由的路由:

routes.MapRoute(
    "New",
    "{lang}/{controller}/{action}/{id}",
    new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional },
    new { lang = "en|de|it|es|fr" }
);
routes.MapRoute(
    "NewEx",
    "{lang}/{controller}/{action}/{id}/{title}",
    new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional, title = UrlParameter.Optional },
    new { lang = "en|de|it|es|fr" }
);

routes.MapRoute(
    "Old",
    "{controller}/{action}/{id}",
    new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
    "OldEx",
    "{controller}/{action}/{id}/{title}",
    new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional, title = UrlParameter.Optional }
);
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我为旧路由提供了语言默认值,因为它不存在于URL中.无论您是否想要,这是您自己的决定,但这种路由可以不重复您的控制器操作.在任何情况下,您都必须定义一种可以这种方式提供的默认语言.

还有一个更大的问题,你是否仍然想要支持旧的URL,或者你宁愿重定向它们(HTTP Redirect Permanent Status 301).

永久重定向

将旧路线更改为:

routes.MapRoute(
    "Old",
    "{controllerOld}/{actionOld}/{idOld}",
    new { controller = "Redirect", action = "Permanent", id = UrlParameter.Optional }
);
routes.MapRoute(
    "OldEx",
    "{controllerOld}/{actionOld}/{idOld}/{titleOld}",
    new { controller = "Redirect", action = "Permanent", id = UrlParameter.Optional, title = UrlParameter.Optional }
);
Run Code Online (Sandbox Code Playgroud)

然后编写一个执行重定向的控制器类:

public class RedirectController : Controller
{
    public ActionResult Permanent(string controllerOld, string actionOld, string idOld, string titleOld)
    {
        return RedirectToRoutePermanent(new {
            lang = "en",
            controller = controllerOld,
            action = actionOld,
            id = idOld,
            title = titleOld
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

解决方案二 - IIS URL重写模块

此解决方案依赖于IIS URL重写模块,您可以在其中将没有语言选择的任何请求重写为首选默认值.

我不会写这里的URL重写是如何工作的,因为有大量的网络资源及其详细信息.


swa*_*eel 4

另一种方法是覆盖 MVC 尝试将请求映射到特定路由之前的内容,但它已经解析了请求 url 并填充了 RouteValues 字典。所以我可以检查语言,如果它没有包含在路由参数中,我可以自己添加它并调用父类的实现来继续。那可能吗?

对的,这是可能的。

您可以覆盖 RouteBase中的GetRouteData,其中将包含 URL 详细信息。

public override RouteData GetRouteData(HttpContextBase httpContext)
{
        string url = httpContext.Request.AppRelativeCurrentExecutionFilePath;
}
Run Code Online (Sandbox Code Playgroud)

并在 global.aspx 中添加以下代码。

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.Add(new MyUrlRoute()); // Add before your default Routes

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
    );
Run Code Online (Sandbox Code Playgroud)

有关更详细的实现 - 请参阅博客 url-manipulation-implementing-routebase.html