ASP.NET MVC + WebForms - 路由冲突

Ron*_*īts 6 asp.net-mvc asp.net-mvc-routing

我正在构建一个简单的报表Web应用程序,用于使用ASP.NET MVC3 + WebForms呈现报表.报表本身由ReportViewer ASP.NET WebForms控件呈现,但我想使用ASP.NET MVC创建参数条目.

我希望所有请求都遵循'〜/ {controller}/{action}/{parameters}'的默认路由方案,除了请求之外~/Report,应该转到报表呈现WebForm.这样做的正确方法是什么?

扩大一点..

我有两个路由Global.asax.cs- 默认的一个,一个用于WebForms页面.

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");
}
Run Code Online (Sandbox Code Playgroud)

URL被渲染得很好,但问题在于,当请求进入时,第一个路由也会占用第二个路由的URL,即~/Report?id=7尝试调用该Index方法ReportController(不存在).

如果我更改它以便'报告呈现'路线在'默认'路线之前,如下所示:

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
    );
}
Run Code Online (Sandbox Code Playgroud)

现在调用Html.ActionLink()呈现不正确的URL,即

`@Html.ActionLink("Report list", "Index", "ReportList")`
Run Code Online (Sandbox Code Playgroud)

呈现

`http://localhost:49910/Report?action=Index&controller=ReportList`
Run Code Online (Sandbox Code Playgroud)

我当前的解决方法首先放置"默认"路由,同时添加正则表达式约束以忽略对"报表"控制器的请求,如下所示:

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

这感觉不干净.再一次,这样做的正确方法是什么?

另外,我还没有决定如何将参数传递给渲染表单:我可以使用查询参数或POST它们.我猜测查询参数更灵活.这里的最佳做法是什么?

编辑:

在研究@LeftyX的答案时,似乎我找到了答案.引用P. Haack的专业ASP.NET MVC 3(命名路由,第9章,第233页)中的路由章节:

... 使用所有路由的名称,并在生成URL时始终使用路由名称.大多数时候,让路由选择你想要用来生成URL的路由实际上是让它失去了机会,这对于强迫控制狂的开发者来说并不是很好.生成URL时,通常可以确切地知道要链接到哪条路径,因此您也可以按名称指定它.

上面提到的部分讨论了与我描述的情况非常相似的情况.

但是因为Html.ActionLink()路由名称参数没有重载,这是否意味着我不能在整个应用程序中的任何地方可靠地使用它,如果有这样的路由?

Lef*_*tyX 1

这是我想出的最好的解决方案。
我已经注册了我的路线MapPageRoute我已将我的报告页面放在名为 Reports 的文件夹下

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 } 
            );
}
Run Code Online (Sandbox Code Playgroud)

我使用 RouteLink 创建了链接,以便您可以指定要使用的路由:

@Html.RouteLink("Report list", "report-rendering", new { id = 7 })
Run Code Online (Sandbox Code Playgroud)

我可以得到在我的 WebForm 页面中获取id,如下所示:

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

希望能帮助到你。

更新

我创建了一个扩展方法来让您的生活更轻松:

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

最好的办法是使用ActionLink而不是WebFormActionLink,但我在签名方面遇到问题,而且我不是这方面的专家。