mostlylucid

STATIC ARCHIVE of mostlylucid.co.uk of old
posts - 916, comments - 758, trackbacks - 11

My Links

News

Archives

Post Categories

Misc. Coding

ASP.NET 4.0: WebForm Routing (quick ’n dirty version)

 

NOTE: This is a quick introduction,. I'll drill into this more in a future post.

One of the things we're adding in ASP.NET 4.0 is built-in support for using Routing together with WebForms. Now, I'm totally aware that this is possible to do already and that a number of people have posted ways of doing this with the Web Routing feature which shipped with ASP.NET 3.5 SP1. We're just adding some features to make it easier to do...

So, what are we adding?

  1. WebFormRouteHandler, this is a simple HttpHandler which you use in defining your routes...it essentially takes care of passing data into the page you're routing to.
  2. Adding HttpRequest.RequestContext and Page.RouteData (this is really just a proxy onto the HttpRequest.RequestContext.RouteData object). Makes it easier to access information passed from the Route.
  3. ExpressionBuilders:
    1. RouteUrl (in System.Web.Compilation.RouteUrlExpressionBuilder), a simple way to create a URL corresponding to your route URL format within an ASP.NET Server Control
    2. RouteValue (again, in System.Web.Compilation.RouteValueExpressionBuilder), a simple way to extract information from the RouteContext.
  4. RouteParameter, a DataSource parameter which lets you easily pass data contained in RouteContext into a query for a DataSource...like FormParameter.

So, how does all this fit together?

WebFormRouteHandler

First, let's define the new WebForm route...as follows:

 

public class Global : System.Web.HttpApplication

{

 

    protected void Application_Start(object sender, EventArgs e)

    {

        RouteTable.Routes.Add("SearchRoute", new Route("search/{searchterm}", new WebFormRouteHandler("~/search.aspx")));

        RouteTable.Routes.Add("UserRoute", new Route("users/{username}", new WebFormRouteHandler("~/users.aspx")));

    }

}

As you can see, we simply map the Route onto a physical page (in the first string, "~/search.aspx"), we've also said that the parameter 'searchterm' should be extracted from the URL and passed into the page.

We also support an additional parameter for WebFormRouteHandler, the signature is as follows:

WebFormRouteHandler(string virtualPath, bool checkPhysicalUrlAccess);

The 'checkPhysicalUrlAccess' parameter specifies whether the RouteHandler should check the perrmissions for the physical page you're routing to (in the case above, search.aspx) as well as the incoming Url...this defaults to 'true'.

HttpRequest.RequestContext and Page.RouteData

Now that you're in the physical page, how do you go about accessing the information which the Routing system has extracted from the Url (or, an object which some other object has added to the RouteData)?

As I mentioned before, we've added two methods...HttpRequest.RequestContext and Page.RouteData. Where Page.RouteData is just a convenience method onto HttpRequest.RequestContext.RouteData

This lets us do the following:

   protected void Page_Load(object sender, EventArgs e)

      {

          string searchterm= Page.RouteData.Values["searchterm"] as string;

          Response.Write(searchterm);

      }

Here, we're just extracting the value we passed in for 'searchterm' defined in the Route above.

Given the url http://localhost/search/scott/ , this would output the word 'scott' into the page...

So, nice...that's how we'd do it in code...but what about Markup?

RouteUrl and RouteValue expression builders

ExpressionBuilders have been described as a 'hidden gem of ASP.NET', and that's a shame...because they're actually pretty cool. We've implemented two new expression builders for WebForm routing. They're used as follows:

 <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="<%$RouteUrl:SearchTerm=Bob%>">Link to search</asp:HyperLink>

Here we're using the RouteUrl expressionbuilder to work out our Url based on a route parameter...the reason for doing this is to save having to hard code in our Url structure into our markup...this of course lets us change the URL structure later.

Based on the route we defined previously, this would generate the Url: 'http://localhost/search/bob', one thing to note is that we automatically work out the correct route based on the input parameters...you can also name the route in this expressionbuilder which lets you define  a specific route url definition to  use.

RouteValue is used like so:

 <asp:Label ID="Label1" runat="server" Text="<%$RouteValue:SearchTerm%>" />

Pretty simple right? Yes, but it avoids you having to mess around with the more complex Page.RouteData["x"] in your markup...

In this case we'd get the value 'scott' inserted into our label's text element.

RouteParameter

Well, just use it like FormParameter e.g.,

         <asp:sqldatasource id="SqlDataSource1" runat="server"  connectionstring="<%$ ConnectionStrings:MyNorthwind %>"

        selectcommand="SELECT CompanyName,ShipperID FROM Shippers where [email protected]"

          <selectparameters>

            <asp:routeparameter name="companyname" RouteKey="searchterm"  />

          </selectparameters>

      </asp:sqldatasource>

I this case we extract the Route parameter 'searchterm' and pass it into the select statement.

Well, that's it for this whistle-stop tour of our new ASP.NET 4.0 WebForm routing feature...

Print | posted on Sunday, January 25, 2009 6:13 PM | Filed Under [ ASP.NET 4.0 ]

Feedback

# Routing for Web Forms in ASP.NET 4.0

Routing for Web Forms in ASP.NET 4.0

1/25/2009 11:07 PM | you've been HAACKED

# ASP.NET 4.0ではルーティングも便利になる(予定)

ASP.NET 4.0: WebForm Routing (quick &amp;#8217;n dirty version) ASP.NET 4.0でルーティングに関してどのような拡張がされる予定であるかが記述されています。...

1/26/2009 12:18 AM | どっとねっとふぁんBlog

# ASP.NET 4.0: WebForm Routing (quick 'n dirty version)

Thank you for submitting this cool story - Trackback from DotNetShoutout

1/26/2009 12:34 AM | DotNetShoutout

# re: ASP.NET 4.0: WebForm Routing (quick 'n dirty version)

Many CMS systems have support for friendly urls. These urls are defined by the content editors and stored in a database table. An un-normalized version of the table might look like this:

Id, UrlPath, FileName
9, /home, default.aspx
-> thus www.mycompany.com/home maps to default.aspx?id=9
12, /about-us/employees/bill, employee.aspx
-> thus www.mycompany.com/about-us/employees/bill maps to employee.aspx?id=12

Since the table can contain thousands- or hundred thousands of rows, then in order to be able to use routing for this, it would have to use the provider model to allow for custom implementations. That way a custom provider that reads from a database or a service can be implemented. Prepopulating the Routes collection with data is not an option due to the amount of data. The data source must therefore be queried for a single route.

Will this be supported or does the RewritePath method still have to be used for doing url rewrite?

1/26/2009 3:52 AM | Lars-Erik Kindblad

# re: ASP.NET 4.0: WebForm Routing (quick 'n dirty version)

This is nice. Here are some thoughts. (1) How does one avoid the hardcode in the statements like... Page.RouteData.Values["searchterm"] ...? Maybe just have an enum of keys? (2) This routing seems certainly RESTful, or at least trending that way-- is that the motivation or case behind the matter? Also, aside from the typical aguments for REST, what about this is significantly different from simple URL-rewriting and/or URL-mapping and/or querystring data passing? That is, how is code like this...
Route("users/{username}" ...which produces something like... http://www.MyWeb.com/Users/BillThomas ...is essentially the same as code like www.MyWeb.com/Users.aspx?Username=BillThomas ...and it has yet to be shown rigorously (IMHO) how the RESTful-approach really differs qualitatively from the querystring-approach. What do you think? Please advise. Thank you. -- Mark Kamoski

1/26/2009 4:06 AM | Mark Kamoski

# re: ASP.NET 4.0: WebForm Routing (quick 'n dirty version)

Pretty clever. I'm never ever going back to webforms, but I can see how this could be useful.

1/26/2009 2:41 PM | Mike

# re: ASP.NET 4.0: WebForm Routing (quick 'n dirty version)

What about abstracting out the application_start routing data into web.config parameters--I'd like to see it go declarative.

I could totally see something like this:

<web.routing>
<route pattern="{controller}{action}{id}" handler="WebFormRouteHandler" />
</web.routing>

1/26/2009 9:44 PM | Tyler Garlick

Gravatar

# re: ASP.NET 4.0: WebForm Routing (quick 'n dirty version)

Lars: yes, it's entirely possible to do this...there's nothing stopping you from building the route definitions based on data from a database. A useful post is from Eilon Lipton weblogs.asp.net/.../...n-asp-net-mvc-and-more.aspx , we use the same underlying Routing feature so Eilon's post has some great tips.
Implementing the parameter mapping stuff is a bit trickier but you could certainly define a route which passed the name parameter then pass this into a DB and returned the correct data...

Tyler: We actually have a prototype of this which one of our interns wrote; actually even cooler as it can define proper objects to pass into the route.Unfortunately we didn't have time to include it. I'll see if we can get it up on Codeplex...

1/27/2009 6:07 PM | scott

# re: ASP.NET 4.0: WebForm Routing (quick 'n dirty version)

Scott,

That would be awesome. Before routing existed my friend and I wrote a library that did this, but it's by far not as robust as the routing libraries are.

I know we ran into problems with declaring routes and having to restart the application. Do you know if the routing libraries encounter the same problems, I know ours was due to a caching issue.

Thanks,

Tyler

1/27/2009 11:04 PM | Tyler Garlick

Comments have been closed on this topic.

Powered by: