Practical ASP.NET
Routing in ASP.NET 4 (Part 2)
Peter continues his exploration of the new Routing features in ASP.NET 4 by showing how to bind control properties to both routes and the values passed in a route.
In my last column (Reduce Maintenance with Routing in ASP.NET 4) I looked both at how routing reduces maintenance costs and how ASP.NET 4 simplifies implementing routing. This column goes into the details of integrating routing with your application.
The example that I've been using is a URL that looks like this:
/mysite.com/customer/vogel/credit_history
Through routing, that URL is converted into a request for a page named Customer.aspx with the values "vogel" and "credit_history" passed to the page as the parameters customerName and mode to the page:
Retrieving parameter values
To retrieve a parameter value in code you use the RouteData object on the Page object. To retrieve the value for the customerName property, you'd use code like this:
If Page.RouteData.Values("customerName") IsNot Nothing Then
Me.CustomerNameTextBox.Text = Page.RouteData.Values("customerName")
End If
However, if you're using the value to update a property on a control, you can just bind the property to the value by entering "RouteValue:customerName" in the property of the control you want to bind. The resulting markup will look something like this:
<asp:TextBox ID="TextBox1" runat="server"
Text="<%$ RouteValue:customerName %>">
</asp:TextBox>
Retrieving Routed URLs
If you're working with a control with a property that accepts a hyperlink (like the HyperLink control's NavigateURL property or the Image control's ImageURL property) you can use the RouteURL expression to retrieve a whole routed URL.
Given one or more parameters, the RouteURL expression will search the routes you've mapped to find one that uses those parameters. It will then insert that URL, with the values you've specified for the parameters, into the page. For instance, this example specifies a value for the customerName parameter in the NavigateURL property of a HyperLink:
<asp:HyperLink ID="LinkToVogel" runat="server"
NavigateUrl="<%$RouteUrl:customerName=vogel%>">
Customer Information for Vogel
</asp:HyperLink>
Assuming that the only routed URL that has a customerName parameter is the one that I've used as my example, this is the HTML that will get passed to the client:
<a id="LinkToVogel" href="/mysite.com/Customer/vogel">
As you can imagine, as you add more mappings to your site, it's not impossible that determining which routing ASP.NET will use to resolve the RouteUrl expression could be difficult. To avoid being surprised, the first step is to assign names to your mappings when you create them. This code, put in the ApplicationStart event of the Global.asax file creates a mapping with the name "CustomerInfo":
Dim rtc As System.Web.Routing.RouteCollection
rtc = System.Web.Routing.RouteTable.Routes
rtc.MapPageRoute("CustomerInfo", _
"Customer/{customerName}/{mode}", _
"~/customer.aspx")
You can then use that name with the routename parameter when binding a property to ensure that you get the routed URL you expect. This example ensures that I get the CustomerInfo URL, for instance, by specifying the routename in the RouteUrl expression along with the parameter value for customerName:
<asp:HyperLink ID="LinkToVogel" runat="server"
NavigateUrl=
"<%$RouteUrl:routename=CustomerInfo,customerName=vogel%>">
Customer Information for Vogel
</asp:HyperLink>
Runtime URL generation
You can't, however, set properties using either the RouteUrl or RouteValue expressions from code: the expressions must be set at design time. Instead, to generate a URL in code you must pass a RouteValueDictionary loaded with the parameter values to the Routes object's GetVirtualPath method. That method returns a VirtualPathData object whose VirtualPath property contains the appropriate routed URL.
This example passes a RouteValueDictionary with the customerName parameter set to Vogel to the GetVirtualPath method along with the name of the mapping that I want ("customerInfo"). The code then uses the resulting VirtualPathData object's VirtualPath to set the NavigateUrl property on a HyperLink control:
Dim rvd As New System.Web.Routing.RouteValueDictionary
rvd.Add("customerName", "Vogel")
Dim vpd As System.Web.Routing.VirtualPathData
vpd = rt.GetVirtualPath(Nothing, "CustomerInfo", rvd)
Me.LinkToVogel.NavigateUrl = vpd.VirtualPath
As I noted in my last column, with ASP.NET 4 Microsoft has reduced the cost of implementing routing, which makes your site more flexible, easier to use and less costly to maintain. As this column has shown, ASP.NET 4 has also added considerably to the functionality in routing.
About the Author
Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.