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

My scenario is as follows: a venue can be part of multiple categories and users can also add filters on multiple category types, so my URLs now are like:

  1. /venues/beaches/boats/themeparks
    (this will display all venues that are beaches AND boats AND themeparks)
  2. /venues/beaches/boats
  3. /venues etc.

So the number of different venue types (beaches, boats, themeparks etc) is both dynamic AND optional.
I decided to go with URLRouting so I can start to get the different values in codebehind via Request.GetFriendlyUrlSegments()

I installed https://www.nuget.org/packages/Microsoft.AspNet.FriendlyUrls.Core/ and manually created a RouteConfig.vb file in App_Start folder. This file contains:

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

And in global.aspx.vb I added:

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

I removed ALL rewrite rules from my application, so no rules in web.config or rewriteRules.config.
When I go to URL: www.example.com/venues, it correctly redirects me to venues.aspx.
But this URL: www.example.com/venues/boats/outside/castles/barns/restaurants, throws a 404 error:
enter image description here

I also checked here and tried that, so enabling http redirection on Windows and changing 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>

I found that when I explicitly define the routes in RouteConfig.vb, it does work, like so:

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

So now URL /venues and /venues/boats/outside/castles/barns/restaurants work, but that is not dynamic at all. Since there are a a lot of venue categories and combinations, I don’t want to add all these combinations manually. I just want to match on all URLs that start with /venues and then use method Request.GetFriendlyUrlSegments in venues.aspx.vb to get the venue categories.

How can I do this?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

I believe you need to add URL patterns to your routes.MapPageRoute call.

A URL pattern can contain literal values and variable placeholders (referred to as URL parameters). The literals and placeholders are located in segments of the URL which are delimited by the slash (/) character.

When a request is made, the URL is parsed into segments and placeholders, and the variable values are provided to the request handler. This process is similar to the way the data in query strings is parsed and passed to the request handler. In both cases variable information is included in the URL and passed to the handler in the form of key-value pairs. For query strings both the keys and the values are in the URL. For routes, the keys are the placeholder names defined in the URL pattern, and only the values are in the URL.

In a URL pattern, you define placeholders by enclosing them in braces ( { and } ). You can define more than one placeholder in a segment, but they must be separated by a literal value. For example, {language}-{country}/{action} is a valid route pattern. However, {language}{country}/{action} is not a valid pattern, because there is no literal value or delimiter between the placeholders. Therefore, routing cannot determine where to separate the value for the language placeholder from the value for the country placeholder.

You can use a couple of different methods to constrain your routes. You can use RegEx, as in:

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

The tiny Regular Expression @”d+ in the code above basically limits the matches for this route to URLs in which the postId parameter contains one or more digits. In other words, nothing but integers, please.

The other option for using route constraints is to create a class which implements the IRouteConstraint interface.

More info from CodeProject.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x