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

时间:2012-02-07 21:59:36

标签: asp.net-mvc asp.net-mvc-3 localization internationalization asp.net-mvc-routing

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

oldUrl -> myapp.com/Item/Details/5/some-title

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

newUrl -> kmyapp.com/en/Item/Details/5/some-title

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

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

任何其他想法也将受到赞赏!

2 个答案:

答案 0 :(得分: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 }
);

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

还有一个更大的问题,您是否仍想支持旧网址,或者您更愿意重定向它们(HTTP重定向永久状态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 }
);

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

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
        });
    }
}

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

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

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

答案 1 :(得分:4)

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

  

是的有可能。

您可以覆盖其中包含网址详情的GetRouteData in RouteBase

public override RouteData GetRouteData(HttpContextBase httpContext)
{
        string url = httpContext.Request.AppRelativeCurrentExecutionFilePath;
}
  

并在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
    );
  

有关更详细的实施,请参阅blog url-manipulation-implementing-routebase.html