2012-03-01 183 views
6

我正在構建一個使用ASP.NET MVC3 + WebForms呈現報表的簡單報表Web應用程序。報告本身由ReportViewer ASP.NET WebForms控件呈現,但我想使用ASP.NET MVC創建參數條目。ASP.NET MVC + WebForms - 路由衝突

我想有所有的請求遵循「〜/ {控制器}/{行動}/{參數}」,除了~/Report請求,這應該去報表呈現的WebForm的默認路由方案。什麼是正確的方法來做到這一點?

擴大一點..

我在Global.asax.cs兩條路線 - 默認的一個,一個用於Web窗體頁。

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

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

    routes.MapPageRoute("report-rendering", "Report", "~/Render.aspx"); 
} 

的網址都會變得很好,但這樣做的問題是,當請求到來時,第一條路線也吃網址,第二個,即~/Report?id=7試圖呼籲ReportControllerIndex方法(這不存在)。

如果我改變它使「報告渲染」路線而來的「默認」路線之前,像這樣:

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

    routes.MapPageRoute("report-rendering", "Report", "~/Render.aspx"); 

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

現在調用到Html.ActionLink()渲染不正確的URL,即

`@Html.ActionLink("Report list", "Index", "ReportList")` 

呈現

`http://localhost:49910/Report?action=Index&controller=ReportList` 

我目前的解決方法提出了 '默認' 路線第一,同時加入正則表達式約束忽略「報告」控制器的請求,就像這樣:

routes.MapRoute(
    "Default", // Route name 
    "{controller}/{action}/{id}", // URL with parameters 
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults 
    new { controller = @"(?!report$).*" } 
); 

這並不覺得乾淨。再次,做這件事的正確方法是什麼?

此外,我還沒有決定如何將參數傳遞給渲染窗體:我可以使用這兩個查詢參數或POST它們。我猜猜查詢參數更靈活。這裏最好的做法是什麼?

編輯:

雖然研究由@LeftyX答案,好像我已經找到了答案。爲了從Professional ASP.NET MVC 3他的路由章(命名路由,第9章,233頁)引述P.哈克:

... 您的所有路由都使用姓名和 始終生成的URL時所使用的路由名稱。大多數情況下,讓路由選擇出你想用來生成一個URL的路由是否真的讓它變成了偶然,這對於強迫控制的畸形開發者來說並不是什麼好東西。在生成URL時,您通常會知道要鏈接到哪條路徑,因此您不妨通過名稱來指定它。

上述部分討論了與我描述的非常相似的情況。

但由於Html.ActionLink()沒有路由名稱參數的重載,這是否意味着我不能在整個應用中的任何地方可靠地使用它,如果有這樣的路由?

回答

1

這是我找到的最佳解決方案。
我登記我的路線與MapPageRoute我已經把我的報告頁面調用報表一個文件夾下)

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

    routes.MapPageRoute(
      "report-rendering", 
      "Report/{id}", 
      "~/Reports/Report.aspx" 
     ); 

     routes.MapRoute(
      "Default", // Route name 
      "{controller}/{action}/{id}", // URL with parameters 
      new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
      ); 
} 

我創建使用RouteLink我的鏈接,以便您可以指定要使用的路線:

@Html.RouteLink("Report list", "report-rendering", new { id = 7 }) 

,我可以得到ID在我的WebForm頁面這樣的:

protected void Page_Load(object sender, EventArgs e) 
{ 
    var id = Page.RouteData.Values["id"] as string; 
} 

希望它有幫助。

UPDATE

我創建了一個擴展方法,使您的生活更輕鬆:

public static class ExtensionMethods 
{ 
    public static MvcHtmlString WebFormActionLink(this HtmlHelper htmlHelper, string linkText, string ruoteName, object routeValues) 
    { 
     var helper = new UrlHelper(htmlHelper.ViewContext.RequestContext); 

     var anchor = new TagBuilder("a"); 
     anchor.Attributes["href"] = helper.RouteUrl(routeName, routeValues); 
     anchor.SetInnerText(linkText); 
     return MvcHtmlString.Create(anchor.ToString()); 
    } 
} 

最好的將是使用ActionLink的,而不是WebFormActionLink但我有簽名問題,我不是這方面的專家。

+0

感謝您的回答。我看到你在那裏做了什麼。由於您添加了{id}參數,因此未爲{id}提供值的.RouteLink()調用不再與路由匹配。 但是,在指定id參數時生成路由將與此路由匹配。 This:@ Html.ActionLink(「Page 1」,「Page」,「Home」,new {id = 1},null) 會生成這個:http:// localhost:49910/Report/1?action =頁面和控制器=首頁 這不是你所期望的,對吧? – 2012-03-01 14:10:35

+0

@ghostskunks:我知道。恐怕您必須使用RouteLink爲WebForms生成鏈接,或者您可以嘗試擴展ActionLink。 – LeftyX 2012-03-01 15:19:49

+0

@ghostskunks:我試着把東西放在一起(更新的答案),但正如我所說,我不是專家。這只是一個想法。 – LeftyX 2012-03-01 15:24:09