ASP.NET 路由:如何使 routeConfig 处理更动态的 URL 结构

ASP.NET Routing: How to make routeConfig handle a more dynamic URL structure

我的场景如下:一个场所可以是多个类别的一部分,用户也可以在多个类别类型上添加过滤器,所以我的 URL 现在是这样的:

  1. /venues/beaches/boats/themeparks (这将显示所有海滩、船只和主题公园的场所)
  2. /venues/beaches/boats
  3. /venues

所以不同场地类型(海滩、船、主题公园等)的数量是动态的和可选的。 我决定使用 URL 路由,这样我就可以开始通过 Request.GetFriendlyUrlSegments()

在代码隐藏中获取不同的值

我安装了 https://www.nuget.org/packages/Microsoft.AspNet.FriendlyUrls.Core/ 并在 App_Start 文件夹中手动创建了一个 RouteConfig.vb 文件。此文件包含:

Public NotInheritable Class RouteConfig
    Private Sub New()
    End Sub
    Public Shared Sub RegisterRoutes(routes As RouteCollection)
        Dim settings = New FriendlyUrlSettings()
        settings.AutoRedirectMode = RedirectMode.Permanent
        routes.EnableFriendlyUrls(settings)
        routes.MapPageRoute("", "venues", "~/venues.aspx")
    End Sub
End Class

并在 global.aspx.vb 中添加:

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
    RouteConfig.RegisterRoutes(RouteTable.Routes)
End Sub

我从我的应用程序中删除了所有重写规则,因此 web.configrewriteRules.config 中没有规则。 当我转到 URL: www.example.com/venues 时,它正确地将我重定向到 venues.aspx。 但是这个 URL: www.example.com/venues/boats/outside/castles/barns/restaurants, 抛出 404 错误:

我也检查了 here 并试过了,所以在 Windows 上启用 http 重定向并更改 web.config:

web.config

<!-- tried setting mode to On/Off/Custom -->
<customErrors mode="Off" defaultRedirect="/error/1" redirectMode="ResponseRedirect">
  <error statusCode="404" redirect="/404.aspx" />
</customErrors>

<modules runAllManagedModulesForAllRequests="true">
  <add type="aspnetforum.ForumSEOHttpModule, aspnetforum" name="ForumSEOHttpModule" />
  <remove name="UrlRoutingModule"/>
  <add name="UrlRoutingModule"
       type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />


</modules>
<handlers>
  <remove name="PHP55_via_FastCGI" />
  <remove name="PHP53_via_FastCGI" />
  <add name="ScriptCombiner" verb="POST,GET" path="ScriptCombiner.axd" preCondition="integratedMode" type="ScriptCombiner, App_Code" />

  <add name="UrlRoutingHandler"
              preCondition="integratedMode"
              verb="*"
              path="UrlRouting.axd"
              type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>


</handlers>

我发现当我在 RouteConfig.vb 中显式定义路由时,它确实有效,如下所示:

routes.MapPageRoute("", "venues", "~/venues.aspx")
routes.MapPageRoute("", "venues/boats/outside/castles/barns/restaurants", "~/venues.aspx")

所以现在 URL /venues/venues/boats/outside/castles/barns/restaurants 有效,但这根本不是动态的。由于场地类别和组合很多,我不想手动添加所有这些组合。我只想匹配所有以 /venues 开头的 URL,然后使用 venues.aspx.vb 中的方法 Request.GetFriendlyUrlSegments 来获取场地类别。

我该怎么做?

我相信你需要添加 URL patterns to your routes.MapPageRoute 调用。

URL 模式可以包含文字值和变量占位符(称为 URL 参数)。文字和占位符位于 URL 的段中,由斜杠 (/) 字符分隔。

发出请求时,URL 被解析为段和占位符,并将变量值提供给请求处理程序。此过程类似于解析查询字符串中的数据并将其传递给请求处理程序的方式。在这两种情况下,变量信息都包含在 URL 中,并以键值对的形式传递给处理程序。对于查询字符串,键和值都在 URL 中。对于路由,键是 URL 模式中定义的占位符名称,只有值在 URL.

在 URL 模式中,您通过将占位符括在大括号({ 和 })中来定义占位符。您可以在一个段中定义多个占位符,但它们必须由文字值分隔。例如,{language}-{country}/{action} 是一个有效的路由模式。但是,{language}{country}/{action} 不是有效模式,因为占位符之间没有文字值或分隔符。因此,路由无法确定在何处将语言占位符的值与国家/地区占位符的值分开。

您可以使用几种不同的方法来限制您的路线。您可以使用 RegEx,如:

routes.MapRoute(name := "BlogPost", url := "blog/posts/{postId}", defaults := New With { _
    Key .controller = "Posts", _
    Key .action = "GetPost" _
}, New With { _
    Key .postId = "\d+" _
})

上面代码中的微型正则表达式@"\d+ 基本上将此路由的匹配限制为 URLs,其中 postId 参数包含一个或多个数字。换句话说,只有整数,请。

使用路由约束的另一个选择是创建一个 class 实现 IRouteConstraint 接口。

More info 来自 CodeProject。