【问题标题】:Depth-first nested routing in an ASP.NET websiteASP.NET 网站中的深度优先嵌套路由
【发布时间】:2025-11-23 18:25:02
【问题描述】:

我一直在探索 System.Web.Routing 命名空间,使用约束等,但我看不到实现这一点的方法。

我正在使用 WebPages/Razor 框架开发一个 ASP.NET 网站(非 WAP、非 MVC)。

我正在尝试实现一种“嵌套路由”形式,其中路由可以包含子路由,只有在父路由匹配时才会尝试;每个孩子都试图匹配 URI 的“剩余部分”。一个“深度优先”的路由匹配搜索,如果你愿意的话。

routes.Add(new ParentRoute("{foo}/{*remainder}", new[] {
    new ParentRoute("{bar}/{*remainder}", new[] {
        new Route("{baz}"),
        new Route("{zip}"),
    }),
    new ParentRoute("{qux}/{*remainder}", new[] {
        new Route("{baz}"),
        new Route("{zip}"),
    }),
));

为简洁起见,我排除了必要的约束/处理程序(在其他参数中)。

在任何情况下,通过树向下的每个步骤都将匹配 URI 的 {*remainder} 尾部。如果一个分支失败,它会向上移动到下一个,本质上是测试如下内容:

foo
  foo/bar
    foo/bar/baz
    foo/bar/zip
  foo/qux
    foo/qux/baz
    foo/qux/zip

现在,我当然不是在问“请写代码”,而是在正确方向的手势。

为了开始实现这样的功能,我希望在 API 中的哪个位置进行查找?我可以找到无数关于编写路由、约束等的教程和信息,但找不到关于扩展路由引擎的教程和信息。


附录
我会继续添加为认股权证

  1. 请注意,我知道从诸如此类的“路由树”生成 URL 会很复杂;这不是我打算实现的。

  2. 我刚刚意识到一种迭代路由生成就足够了;所以我想我会尽快将其作为可能的答案发布。不,它不会。边缘情况太多。

【问题讨论】:

  • 你看过IRouteHandler吗?我已经将它用于完全不同的情况但同样的问题并且效果很好。 (它在一个 MVC 项目中)
  • @cheesemacfly 是的,我一直在玩它以尝试使 POC 运行,但我不知道要创建什么以从 GetHttpHandler 返回以继续路由过程。感谢您的建议,我会继续挖掘。
  • 它需要从实现IHttpHandler的类中返回一个对象。在我的例子中,使用 MVC 框架,这个对象的类型是 MvcHandler。不确定它会帮助你...
  • @cheesemacfly 没错,我一直在尝试设计一个新的伪应用程序类来充当处理程序,并重新启动(继续)路由过程,最终返回控制成功(或失败)的发起者,但我无能为力。

标签: asp.net routing depth-first-search


【解决方案1】:

我有以下代码,但有一点我不确定你想如何处理它:你知道最多有多少个孩子可以拥有一条路线吗?

在 Global.asax 中:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.Add(new Route("test/{path}", new RouteValueDictionary { { "path", string.Empty } }, new TestingRouteHandler()));
    }

TestingRoutHandler 类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Routing;
using System.Web;
using System.Web.UI;
using System.Web.Compilation;

namespace WebApplication1
{
    class TestingRouteHandler : IRouteHandler
    {
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            //This is where you should treat the request, test if the file exists and if not, use the parent part of the url
            string aspxFileName = string.Format("~/{0}.aspx", requestContext.HttpContext.Request.Url.PathAndQuery.Replace("/", string.Empty));

            return (IHttpHandler)BuildManager.CreateInstanceFromVirtualPath(aspxFileName, typeof(Page)) as Page;
        }
    }
}

【讨论】: