路线始终转到第一个maproute

Adr*_*ian 5 c# asp.net-mvc routing asp.net-mvc-routing asp.net-mvc-2

我正在尝试创建看起来像这样的URI: http://hostname/mobile/en/controller/action用于移动设备或http://hostname/en/controller/action用于桌面(非移动设备).

我的路由表目前看起来像这样(Global.asax.cs)

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Mobile", // Route name
            "mobile/{language}/{controller}/{action}/{id}", // URL with parameters
            new { language = "en", controller = "Route", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
            new { language = @"en|us" } // validation
        );
        routes.MapRoute(
            "Default", // Route name
            "{language}/{controller}/{action}/{id}", // URL with parameters
            new { language = "en", controller = "Route", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
            new { language = @"en|us" } // validation
        ); 
Run Code Online (Sandbox Code Playgroud)

当我尝试执行a时,会出现问题. return RedirectToAction("Add", "User"); 它总是将桌面浏览器重定向/en/User/List/mobile/en/User/Add我想要的时间/en/User/Add.移动版本可以正常工作但我相信这是因为第一个"移动"路由始终被视为匹配的路由,即使它在开始时没有/ mobile /.

我正在尝试为两个版本使用相同的控制器,但我坚持它总是重定向到移动路由.这意味着RedirectToRoute不完美,因为我想要动态路线.

谢谢你的帮助.

Ren*_*ink 2

主要问题是您提供的路由值与两条路由匹配,这意味着它将采用第一个路由(移动)。

您可以通过重定向到路由而不是操作来手动选择要使用的路由。

return RedirectToRoute("Mobile", new {
    language = "en", controller = "User", action = "Get", id = 20
});
Run Code Online (Sandbox Code Playgroud)

对于移动或

return RedirectToRoute("Default", new {
    language = "en", controller = "User", action = "Get", id = 20
});
Run Code Online (Sandbox Code Playgroud)

作为您的默认路线。

然而,这给你带来了一个新问题:获取当前路由的名称。正如示例中所见,引用命名路由是很有可能的。然而,获取当前使用的路线的名称似乎是不可能的。使用类似于查看当前 URI 的 hack 方式显然是不可取的。除了丑陋(黑客)之外,它还可能导致大量代码重复。

然而,可以向路由添加值,这些值可以轻松地从控制器(或视图)获取:

routes.MapRoute(
    "Mobile", // Route name
    "mobile/{language}/{controller}/{action}/{id}", // URL with parameters
    new { routeName = "Mobile", language = "en", controller = "Route", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
    new { language = @"en|us" } // validation
);
routes.MapRoute(
    "Default", // Route name
    "{language}/{controller}/{action}/{id}", // URL with parameters
    new { routeName = "Default", language = "en", controller = "Route", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
    new { language = @"en|us" } // validation
);
Run Code Online (Sandbox Code Playgroud)

现在,您可以在代码中使用路由本身提供的值重定向到当前路由:

return RedirectToRoute(RouteData.Values["routeName"], new {
    language = "en", controller = "User", action = "Get", id = 20
});
Run Code Online (Sandbox Code Playgroud)

现在,如果您想让它变得完全奇特,您甚至可以从中创建一个扩展方法:

public static class ControllerExtensions {
    public static RedirectToRouteResult CustomRedirectToRoute(this Controller controller, string controllerName, string actionName, object routevalues) {
        return CustomRedirectToRoute(controller, controllerName, actionName, new RouteValueDictionary(routevalues));
    }

    public static RedirectToRouteResult CustomRedirectToRoute(this Controller controller, string controllerName, string actionName, RouteValueDictionary routevalues) {
        routevalues = routevalues ?? new RouteValueDictionary();
        routevalues.Add("controller", controllerName);
        routevalues.Add("action", actionName);
        return new RedirectToRouteResult(controller.RouteData.Values["routeName"] as string, routevalues);
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这能为您的问题提供一个很好的解决方案!