【问题标题】:ASP.NET MVC + WebForms - route conflictASP.NET MVC + WebForms - 路由冲突
【发布时间】:2012-03-19 19:15:33
【问题描述】:

我正在构建一个简单的报表 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");
}

URL 渲染得很好,但问题是当请求进来时,第一个路由也吃掉第二个路由的 URL,即~/Report?id=7 尝试调用 Index 上的 @987654327 方法@(不存在)。

如果我将其更改为“report-rendering”路由位于“Default”路由之前,如下所示:

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 的答案时,我似乎找到了答案。引用 P. Haack 在Professional ASP.NET MVC 3 中的路由章节(命名路由,第 9 章,第 233 页):

... 为您的所有路线使用名称和 生成 URL 时始终使用路由名称。大多数时候,让 Routing 排序 您想用来生成 URL 的路由实际上是靠运气,这不是 与强迫症控制狂开发者相处得很好。生成 URL 时,通常 确切地知道您要链接到哪个路由,因此您不妨按名称指定它。

上述部分讨论了与我描述的情况非常相似的情况。

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

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-routing


    【解决方案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 } 
                );
    }
    

    我已经使用 RouteLink 创建了我的链接,因此您可以指定要使用的路线:

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

    我可以像这样在我的 WebForm 页面中获取 id

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

    希望对你有帮助。

    更新

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

    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,但我在签名方面遇到问题,而且我不是这方面的专家。

    【讨论】:

    • 感谢您的回答。我看到你在那里做了什么。因为您添加了 {id} 参数,所以没有为 {id} 提供值的 .RouteLink() 调用不再匹配路由。但是,在指定 id 参数的同时生成路由将匹配此路由。这个:@Html.ActionLink("Page 1", "Page", "Home", new { id = 1 }, null) 将生成这个:localhost:49910/Report/1?action=Page&controller=Home 这不是你所期望的,对吧?
    • @ghostskunks:我知道。恐怕您必须使用 RouteLink 为 WebForms 生成链接,或者您可以尝试扩展 ActionLink。
    • @ghostskunks:我试图把一些东西放在一起(更新的答案),但正如我所说,我不是专家。这只是一个想法。
    • 您的方法可能有效。由于链接渲染需要提供所有路由参数值,因此如果您指定唯一的参数名称,例如 reportId 而不是 id,并且不指定默认值,则链接渲染不会选择此路由。即,使用routes.MapPageRoute("report-rendering","Report/{reportId}", "~/Render.aspx"); 的路线,此:@Html.ActionLink("Page 2", "Page", "Home", new { id = 2 }, null) 生成:localhost:49910/Home/Page/2,但此:@Html.RouteLink("Run report", "report-rendering", new { reportId = 1 }) 将生成:localhost:49910/Report/1
    • 感谢您的更新和扩展方法,但是在生成链接以进行报告呈现的站点上这不是问题——人们总是可以在那里使用 Html.RouteLink() 并提供一个名称。问题是必须始终在其他页面使用 RouteLink(),否则 ActionLink() 可能会生成不正确的链接。
    猜你喜欢
    • 2016-04-17
    • 2016-01-06
    • 1970-01-01
    • 2011-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多