2010-06-23 68 views
5

我想創建看起來有點像這樣的URI: http://hostname/mobile/en/controller/action手機或http://hostname/en/controller/action桌面(非手機)。路由總是去第一個maproute

我的路由表目前看起來像這樣(的Global.asax.cs),當我嘗試做一個 return RedirectToAction("Add", "User"); 它時,我想從/en/User/List桌面瀏覽器總是重定向到/mobile/en/User/Add發生

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

問題它要去/en/User/Add。 移動版本可以正常工作,但我相信這是因爲第一個「移動」路線始終被視爲匹配的路線,即使它在開始時沒有/ mobile /。

我試圖使用相同的控制器兩個版本,但我堅持它總是重定向到移動路線。這意味着RedirectToRoute不是完美的,因爲我想要動態路線。

感謝您的幫助。

回答

2

主要問題是您提供的路由值與兩個路由匹配,這意味着它將採用第一個路由(即移動路由)。

您可以通過重定向到路由而不是操作來手動選擇要使用的路由。

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

移動或

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

您的默認路由。

但是,這會給您帶來一個新問題:獲取當前路線的名稱。如示例所示,提及的命名路線非常有可能。 然而,獲得當前使用路線的名稱似乎是不可能的。顯然不希望使用像查看當前URI那樣的黑客攻擊。除了醜陋(黑客)之外,它還可能導致大量代碼重複。

然而,有添加值,其可以從控制器(或視圖)可以容易地獲得的路由的可能性:

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

現在從你的代碼可以通過使用值重定向到當前路線從路由本身提供:

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

現在,如果你想這完全看中了,你甚至可以提出延期方法出這一點:

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

希望這能爲您的問題提供一個很好的解決方案!

+0

非常感謝René,看起來就像我希望做的一樣。 你能告訴我哪裏最好的地方是把擴展方法? – Adrian 2010-06-28 09:08:04

+1

將靜態類ControllerExtensions放置在您想要的任何位置。在控制器中,您想要使用重定向,請確保包含擴展類所在的名稱空間。然後,在控制器中的任何位置,可以使用this.CusomRedirectToRoute(「Home」,「Index」,routeValues); 如果需要,還可以添加另一個將null作爲routeValues值的擴展方法。 – 2010-06-30 12:32:49

+0

如果你想整理它,我的評論的後半部分可以用整潔乾淨的系統來取代這個帖子中描述的路線名稱:http://stackoverflow.com/questions/363211/how - 可以-I-GET-的路線名稱,在控制器功能於ASP淨MVC – 2010-06-30 20:44:38