Monday, August 18, 2008

Asp.Net Routing

New to the .Net Framework 3.5 SP 1 is the System.Web.Routing namespace.  The classes in the routing namespace allow you to use urls that do not map to a web page.


For this example I created a new web application.  To start off with lets add a reference to the system.web.routing and system.web.abstractions.  Open up the web.config file and lets add the UrlRoutingModule to the httpmodules section

        <httpModules>
            <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    </httpModules>

Next we need to add a WebFormRouteHandler class which will be our route handler.

Imports System.Web.Routing
Imports System.Web.Compilation
Public Class WebFormRouteHandler
    Implements IRouteHandler
    Private _Path As String
    Public Property Path() As String
        Get
            Return _Path
        End Get
        Set(ByVal value As String)
            _Path = value
        End Set
    End Property
    Public Sub New(ByVal p As String)
        Path = p
    End Sub
    Public Function GetHttpHandler(ByVal requestContext As System.Web.Routing.RequestContext) As System.Web.IHttpHandler Implements System.Web.Routing.IRouteHandler.GetHttpHandler
        For Each value In requestContext.RouteData.Values
            requestContext.HttpContext.Items(value.Key) = value.Value
        Next
        If Not String.IsNullOrEmpty(Path) Then
            Return TryCast(BuildManager.CreateInstanceFromVirtualPath(Path, GetType(Page)), IHttpHandler)
        Else
            Return Nothing
        End If
    End Function
End Class

Finally we have to add global.asax so we can start the routing when the web site starts up


Imports System.Web.SessionState
Imports System.Web.Routing
Public Class Global_asax
    Inherits System.Web.HttpApplication
    Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
        ' Fires when the application is started.
        Dim userHandler As New WebFormRouteHandler("~/user.aspx")
        With RouteTable.Routes
            ' pattern of the url to match
            .Add(New Route("user/{user}", userHandler))
        End With
    End Sub
    Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
        ' Fires when the session is started
    End Sub
    Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
        ' Fires at the beginning of each request
    End Sub
    Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs)
        ' Fires upon attempting to authenticate the use
    End Sub
    Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
        ' Fires when an error occurs
    End Sub
    Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
        ' Fires when the session ends
    End Sub
    Sub Application_End(ByVal sender As Object, ByVal e As EventArgs)
        ' Fires when the application ends
    End Sub
End Class

Finally we need 2 web pages

Default.aspx

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="RoutingTest._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <h1>ASP.NET System.Web.Routing with WebForms sample</h1>
    <div><a href="user/ken">User test</a></div>
    </div>
    </form>
</body>
</html>

user.aspx
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="User.aspx.vb" Inherits="RoutingTest.User" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
            <h1>
            Users</h1>
        <div>
            User:
            <%=Context.Items("user")%></div>
        <hr />
        <div>
            Change the user in the URL.</div>
        <div>
            The WebFormRouteHandler adds the matched values to the HTTPContext.Items collection
            (exists for lifetime of request only).</div>
    </div>
    </form>
</body>
</html>

Hope this helps