6

我想通过一些增强来实现与这个问题非常相似的东西。

有一个 ASP.NET MVC Web 应用程序。

我有一棵实体树。
例如,Page有一个名为 Children 的属性的类,其类型为IList<Page>。(Page类的一个实例对应于数据库中的一行。)

请注意,网站所有者可以随时添加新页面或删除现有页面,并且 URL 也应反映这些更改。

我想为Page数据库中的每个人分配一个唯一的 URL。
Page使用一个名为PageController.

示例网址:

http://mysite.com/Page1/
http://mysite.com/Page1/SubPage/
http://mysite.com/Page/ChildPage/GrandChildPage/

你得到图片。
所以,我希望每个Page对象都有自己的 URL,等于其父 URL 加上自己的名称。
除此之外,我还希望能够将单个映射Page/(根)URL。

我想应用这些规则:

  1. 如果 URL 可以使用任何其他路由处理,或者文件系统中存在指定 URL 的文件,则让默认 URL 映射发生
  2. 如果虚拟路径提供程序可以处理 URL,则让其处理
  3. 如果没有其他,则将其他 URL 映射到PageController该类

我也发现了这个问题还有这个问题和这个问题,但它们并没有太大帮助,因为它们没有提供关于我的前两点的解释。

我看到以下可能的解决方案:

  • 为每个页面单独映射一条路线。
    这需要我在应用程序启动时遍历整个树,并将完全匹配的路由添加到路由表的末尾。
  • 我可以添加一个路由{*path}并编写一个IRouteHandler处理它的自定义,但是我看不出我该如何处理前两个规则,因为这个处理程序将处理所有事情。

到目前为止,第一个解决方案似乎是正确的,因为它也是最简单的。但是,即使在那种情况下,我也不确定如何PageController处理请求。

我非常感谢您对此的想法。

先感谢您!

编辑:我现在有时间检查我收到的每个答案的各个方面。我接受了尼尔的回答,因为他是对事情如何运作提供最佳解释的人。我还赞成所有其他答案,因为它们提供了好主意。

4

4 回答 4

3

路由按照添加到集合中的顺序进行处理。您可以在现有路由之后添加自定义路由,以确保它是最后一个有机会处理请求的路由。这将允许您在其之前添加现有文件(虚拟或其他)的路由,因此满足标准 1 和 2。

默认情况下,MVC 路由将在应用存储在路由集合中的任何路由之前路由到现有文件;请参阅http://msdn.microsoft.com/en-us/library/system.web.routing.routecollection.routeexistingfiles.aspx。(对保罗的帽子 - 见评论)。

要将请求路由到您的页面控制器,只需创建一个自定义路由来检查虚拟路径,如果它与数据库中页面的模式匹配,则返回RouteData. 使用从虚拟路径中提取的适当值进行设置RouteData(例如,将 Path 键设置为 /Parent/Child/Grandchild),将控制器键设置为您的页面控制器名称(例如 Page),并将操作设置为该操作的名称你想要执行(例如显示)。RouteData应该使用MvcRouteHandler(不确定这是否是正确的类名)创建。

为确保正确返回数据库驱动页面的 url,覆盖GetVirtualPath( RequestContext, RouteValueDictionary )方法RouteBase并使用传入的路由值来确定这是否是数据库驱动页面以及是否创建所需的虚拟路径数据(否则返回 null)。

有关覆盖GetRouteDataand的帮助GetVirtualPath,请查看 and 的反射源System.Web.Routing.RouteBase代码System.Web.Routing.Route;之后谷歌是你的朋友。

反向使用路由来确定给定控制器、操作和任何其他路由值的 url。您应该能够利用它在被请求的上下文中构建页面的 url。

于 2010-05-31T01:41:07.727 回答
1

一种不同的想法是使用 T4(文本模板转换工具包)读取您的孩子一次并生成 Global.asax 文件的内容。

编辑:基本上使用 T4,您可以自动生成文本文件。例如,INSERT INTO [MyTable] (Text) VALUES (@ItemText)您可以让 T4 引擎读取集合并为您生成这些插入语句,而不是手动复制一些大型集合中的项目并将它们与某些特定上下文一起粘贴到文本文件(如 )中。它是静态的,不适用于运行时。

我发现Pro Entity Framework 4.0书中有一个很好的介绍。

但是如果你说你需要动态地做,这可能不适合你。

于 2010-05-23T10:40:31.563 回答
1

保存页面时,您知道页面结构。因此,您可以为每个页面生成 URL 并将其保存到数据库记录中。然后您可以使用{*path}规则并在数据库中查找完全匹配。此规则应位于您的规则定义中的最后一个,以便您可以匹配其他路由。

例如,您Page1没有父页面,它的 url 是Page1. 你SubPage知道它是父母,所以它可以 ganate urlPage1/SubPage等。

于 2010-06-05T14:25:55.497 回答
1

你可以使用一个"Page/{*path}"模式。然后,您可以通过拆分“/”上的字符串来分解路径并遍历它,或者您可以使用 Rarouš 将 [生成的] 路径存储在数据库中的建议并进行直接查找。

如果您使用 Rarouš 的方法,那么当父路径更改时,您将必须为所有子项更新表中的路径条目。这可以通过一个更新查询简单地完成。

我假设您正在映射您希望在配置文件或表条目中某处用于主页的页面。您可以让主页控制器进行查找并返回要呈现的主页视图的内容(您可以使用共享视图、部分视图或调用页面控制器,这样您就不会重复行为),或者你可以让它重定向到那个页面。

使用这种技术,您可以拥有一个以相同方式处理所有这些页面的页面控制器和视图。您的其他要求似乎由 MVC 框架自动处理。

您的路径将如下所示:

http://mysite.com/Page/Page1/ 
http://mysite.com/Page/Page1/SubPage/ 
http://mysite.com/Page/Page/ChildPage/GrandChildPage/ 

您当然可以使用“页面”以外的前缀。

于 2010-06-07T10:10:48.587 回答