2014-09-19 105 views
0

我們正在將遺留應用遷移到.NET MVC,並且必須保持舊URL的向後兼容性。考慮一個論壇應用程序中的URL看起來像這樣基於查詢參數的ASP.NET MVC自定義路由

http://example.com/forums?page=ForumsList - shows a list of all forums 
http://example.com/forums?page=Threads&forumId=1 - shows list of threads in forum 1 
http://example.com/forums?page=Posts&forumId=1&threadId=1 - shows posts in forum 1, thread 1. 

我想在我的控制器來操作這些相同的URL映射,即

public ActionResult ForumsList(){} 
public ActionResult Threads(string forumId){} 
public ActionResult Posts(string forumId, string threadId){} 

沒有複製該維護的噩夢,我們在我們的傳統了系統

public ActionResult Index(string page){ 
    if (page == "Forums"){ 
     return Forums(); 
    } 
    else if (page == "Threads){ 
     return Threads(Request.Params["forumId"]); 
    } 
    else if (page == "Posts"){ 
     return Posts(Request.Params["forumId"], Request.Params["threadId"]); 
    } 
    // oh, there's more. a lot more. 
} 

所有我能找到自定義路由的文件似乎表明,它只能解析URL,而不是則params的路徑部分。我嘗試了以下,無濟於事:

 routes.MapRoute(
      name: "TestRoutes", 
      url: "{controller}/?page={action}", 
      defaults: new {controller = "Forums", action = "ForumsList"}); 

我還能做什麼?

+1

你看過IIS重寫模塊,它會攔截請求並將它們重新引導或將它們重定向到新路由,然後它們碰到asp.net處理程序並被路由到適當的控制器。它支持相當不錯的正則表達式模式匹配。你可以很容易地將'forums?page = Threads&forumId = 1'改寫成類似於'/ forums/threads/1'的文件。 – 2014-09-19 14:19:25

+0

你是這樣的路由示例: ** routes.MapRoute( name:「TestRoutes」, url: {}控制器/頁= {}行動」, 默認:新{控制器= 「?論壇」,行動= 「ForumsList」}); ** 你試過: ** routes.MapRoute( 名稱: 「TestRoutes」, url:「{controller} /?page = {action}」, 默認值:new {controller =「Forums」,action =「{action}」); ** – Pheonyx 2014-09-19 14:34:53

回答

1

其實,你不需要做任何特別的事情。默認情況下,模型綁定器將嘗試將查詢字符串中的任何內容作爲參數添加到操作方法中。你只需要使用一個動作來處理/代理的所有請求:

public class ForumsController : Controller 
{ 
    public ActionResult Index(string page, int? forumId, int? threadId) 
    { 
     ... 
    } 
} 

只需的默認路由:

routes.MapRoute(
    name: "Default", 
    url: "{controller}/{action}/{id}", 
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
); 

會工作得很好。

該URL的主要位/forums將匹配ForumsController,並且將使用缺省動作Index,因爲它沒有在URL中指定。 id參數是可選的。然後,查詢字符串中的每個項目都將設置爲該操作的同名命名參數。 forumIdthreadId參數需要爲空,以允許傳遞page參數,例如/forums?page=ForumsList URL。

儘管您可以簡單地將您的應用程序設置爲以這種方式工作,但實際上我建議將此特定操作保留爲交換中心。首先,我想創建一個自定義路由,所以您不必花你Index行動在:

routes.MapRoute(
    name: "OldForums", 
    url: "forums", 
    defaults: new { controller = "OldForums", action = "RedirectToNewURLs" } 
); 

然後:

public class OldForumsController : Controller 
{ 
    public ActionResult RedirectToNewURLs(string page, int? forumId, int? threadId) 
    { 
     if (page == "ForumList") 
     { 
      return RedirectToActionPermanent("Index", "Forums"); 
     } 

     if (page == "Threads") 
     { 
      return RedirectToActionPermanent("Threads", "Forums", { id = forumId }); 
     } 

     // etc 
    } 
} 

這些重定向將指向新的好的論壇網址如/forums/{id}/threads。因此,如果用戶通過舊網址輸入內容,他們只會被重定向到新版本,並且所有新用戶都會從一開始就被髮送到正確的網址。

編輯

其實,我忘了指出,一個併發症這種方法是,你不能真正使用URL /forums爲您的實際論壇指標。你可以使用像/forums/all這樣的東西來區分,或者只是做一些像單數化的東西,例如forum。所有其他路由都可以與forums前綴正常工作,因爲只有該字符串本身才會與自定義路由匹配。例如,像forums/1這樣的內容會落入默認路由。