Serving the Florida .NET Developer Communities (a Joe Healy production)
Bizspark Program

ASP.NET Routing in VB 3.5 Web Forms
Posted on 3/23/2010 7:14:35 PM

Updated 2010/04/12 3:30P EST... added notes for configuring IIS on pre-IIS7 machines

Updated 2010/04/01 7:30P EST... left out the web.config section changes accidentally

ASP.NET Routing is a mechanism for 'routing' URLs that aren't so nice or friendly to other parsing or organizational mechanisms. Typically to date we've seen routing in ASP.NET MVC applications, or something similar for general IIS apps using IIS URL Rewriting. .NET 3.5 is straight up is fairly awkward to setup simple web routes for traditional web forms applications. .NET 4.0 has web forms routes baked in by default.

URL routing is wonderful for SEO. Developers quickly become enamored with the SEO compliant, 'friendly' URL mechanism. For example, something like "http://www.devfish.net/fullblogitemview?blogid=1072" is not as SEO friendly or pretty or user friendly as "http://www.devfish.net/blogitem/implementing urlrouting in existing aspnet35 applications". Naturally I was extolling the virtues of MVC2 and .NET 4.0 Webforms and such. At that point, an attendee asked me how to implment URL routing into their existing ASP.NET 3.5 SP1 VB Webforms Application.

Why would the attendee want to url routing in .NET 3.5 SP1 webforms? Wouldn't MVC or .NET 4.0 have been a better route? Technically sure, but it didn't make sense for them right now. Due to various constraints, moving to MVC or .NET 4 was not a feasible option for this application. .NET and/or MVC were targets in their future, sure, but just not right now. The customer was targeting implementing some new functionality inside the 3.5 webforms, and wanted to build pages with URLs that could be carried forward into MVC easily, as well as providing some SEO type benefits now.

Chris Cavanagh put out a great implementation of URL routing in 3.5 SP1 webforms in VB here. Naturally I pointed the customer to that and said "have fun". The next day the customer emailed me with basically "great, a complete website doing routing, but how do I integrate that into my site?". So I thought I'd spell out for ya'll the steps I had them take to implement Cavanagh's routing into an existing ASP.NET 3.5 SP1 application. The "routing implemented" files can be found at http://www.devfish.net/downloads/files/VBASPNET35RoutingImplemented.zip .

Step 1: Get the goodies -- Go get Cavanagh's VB webforms example from http://chriscavanagh.wordpress.com/2009/01/20/aspnet-routing-in-vbnet/. We're going to steal, er ah liberate, er ah, reuse some/all of his goodies into our existing app. Extract it out into a folder somewhere.

Step 2: Reference it -- [Add Reference] via the Visual Studio Add Reference Dialog, for System.Web.Routing and System.Web.Abstractions. Those namespaces are necessary to support our routing implementation.

Step 3: Liberate the routables -- copy in the RoutablePage.vb, RoutingHander.vb, WebFormRouteHandler.vb from Cavanagh's stuff to your project. If you are working in ASP.NET Web Site and not an ASP.NET project type, these files would go into the App_Code directory.

Step 4: going global -- If there's not a global.asax file in the project, add a global.asax file

Step 5: global namespace -- Add the namespace for System.Web.Routing to the global.asax file. See snippet below

<%@ Application Language="VB" %>
<%@ Import Namespace="System.Web.Routing" %>
<script runat="server"> 
...
</script>

Step 6 and 7: routes in global.asax -- add your basic routes to your global.asax file by creating a register routes function. You can see the ones I used from the demo project below. Also wire in your Application_Start handler to call RegisterRoutes with your route table

    Private Sub RegisterRoutes(ByVal routes As RouteCollection)
        routes.Add(New Route("Welcome", New WebFormRouteHandler("~/Welcome.aspx")))
        routes.Add("nameSearch", New Route("community/{searchterm}", New WebFormRouteHandler("~/Search.aspx")))
        routes.Add("usergroupSearch", New Route("community/usergroups/{searchterm}", New WebFormRouteHandler("~/UserGroup.aspx")))
        routes.Add("usergroupbyid", New Route("community/usergroups/id/{usergroupid}", New WebFormRouteHandler("~/UserGroup.aspx")))
        routes.Add("eventsSearch", New Route("community/events/{searchterm}", New WebFormRouteHandler("~/CommunityEvents.aspx")))
        routes.Add("eventsbyid", New Route("community/events/id/{eventid}", New WebFormRouteHandler("~/CommunityEvents.aspx")))
        routes.Add("eventsbytype", New Route("community/events/type/{eventtype}", New WebFormRouteHandler("~/CommunityEvents.aspx")))
        routes.Add("eventsbydaterange", New Route("community/events/daterange/{daterange}", New WebFormRouteHandler("~/CommunityEvents.aspx")))
    End Sub

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

Step 8: modify your web.config to support routing in the system.web and system.webServer sections

    <system.web>    
    <httpModules>
    ...
    <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    </httpModules>
    
    <system.webServer>
    ...
    <modules>
    ...
    <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </modules>        

Step 9: setup a test page to call some routes in -- Here we'll use a pretend events page as our handler and slap them into welcome.aspx

community/events/{searchterm} - search events for anything with searchterm in it - <a href="community/events/sql server">community/events/sql server</a>
community/events/id/{eventid} - search any event ids exact or patially matching - <a href="community/events/id/SFL123">community/events/id/SFL123</a>
community/events/type/{eventtype} - list upcoming events of this type - <a href="community/events/type/silverlight">community/events/type/silverlight</a>
community/events/daterange/{daterange} - list events in this date range - <a href="community/events/daterange?start=2010-02-11&end=2010-02-14">community/events/daterange?start=2010-02-11&end=2010-02-14</a>

Step 10: process the routes in the receiving page - in this case its "communityevents.aspx" - pull the key/value pairs out of the routing info, see what they key is, process any query strings, and have fun

        _out.Append(String.Format("# of search terms = [{0}]<br/>", RequestContext.RouteData.Values.Count()))

        For _ii As Integer = 0 To RequestContext.RouteData.Values.Count() - 1
            _out.Append("routedata #" & (_ii + 1))
            _out.Append("<br/>")
            Dim _key As String = (RequestContext.RouteData.Values.Keys(_ii))
            Dim _value As String = RequestContext.RouteData.Values.Values(_ii)
            _out.Append(String.Format("[{0}]=[{1}]", _key, _value))
            _out.Append("<br/>")

            If (_key = "searchterm") Then
                _searchterm = _value
            ElseIf (_key = "eventid") Then
                _eventid = _value
            ElseIf (_key = "eventtype") Then
                _eventtype = _value
            End If

            'special logic
            If (_searchterm = "daterange") Then
                _daterange = String.Format(String.Format("{0} to {1}", Request.QueryString("start"), Request.QueryString("end")))
            End If
        Next

        _out.Append(String.Format("general search: anything with [{0}] in it<br/>", _searchterm))
        _out.Append(String.Format("event group by id: id matching [{0}]<br/>", _eventid))
        _out.Append(String.Format("event group by type: id matching [{0}]<br/>", _eventtype))
        _out.Append(String.Format("events in daterange [{0}]", _daterange))

Step 10: if you are using a version of IIS lower than 7.0 you need to setup a 'wildcard mapping'. see this kb for details...

Happy routing. Hopefully this will sustain you until you can get over to .NET 4.0 or get a good look at ASP.NET MVC2.



The opinions expressed on this website are Joe Healy's and Joe Healy's alone, and have nothing whatsoever to do with my employers views of the world Applied Innovations
Hosted by Applied Innovations
devfish v2010_35fw:3.0