What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

When I wrote the first post in this series, there was tremendous amount of interest generated and also a lot of feedback requesting to post some of the advanced features.  Like I said earlier, ASP.NET 4.0 has lots of new features some of them as simple as Page.Title whereas so as big as caching improvements.  This post covers one such feature which is Routing in Webforms.  Although Routing was available even in .NET 3.5 SP1, (check this excellent post by Phil Haack on implementing Routing in ASP.NET 3.5 with .NET 3.5 SP1), it was kind of less known.  Also the plumbing work was too much for getting it implemented.

However, this has been much simplified in ASP.NET 4.0.  To give a background, System.Web.Routing is the namespace that provides the all important RouteTable & PageRouteHandler class.  Initially System.Web.Routing was an integral part of ASP.NET MVC.  However, the team must have anticipated that Routing is more important even for Webforms and hence they moved this DLL outside the scope of just MVC and made it available to Webforms as well. 

Importance of Routing:  Getting friendlier URLs which help in better search engine optimization and indexing.  Cleaner URLs that can be bookmarked than the unfriendly querystring based approach.  As more and more URLs are available, the chances of improvement in search engine ranking becomes higher.  These are some of the general advantages of Routing and friendly URLs. 

Ok, now that the context is established, lets start with our sample.  To begin with, I am using Visual Studio 2010 Beta 1 (download link) and Northwind Sample Database (download link)

I created a “File – New Project – ASP.NET Web Application” leaving the default .NET 4.0 as the framework option. Then, I created a bunch of pages i.e Products.aspx, Categories.aspx and also the Global.asax (Add – New Item – Global Application Class)

On the Default.aspx page, I added a GridView and configured it to use the Northwind Database Connection String and the Categories Table therein.  I modified the auto-generated bound columns with a Template Column to accomodate our link to Categories Page.  The modified GridView code looks as below:-

<asp:GridView ID="GridView1" runat="server" AllowPaging="True"
            AllowSorting="True" AutoGenerateColumns="False" CellPadding="4"
            DataKeyNames="CategoryID" DataSourceID="SqlDataSource1" ForeColor="#333333"
            GridLines="None">
            <AlternatingRowStyle BackColor="White" />
            <Columns>
               <asp:TemplateField HeaderText="CategoryName" SortExpression="CategoryName">
                    <ItemTemplate>
                   
    <a href="Categories/<%# Eval("CategoryName") %>"><asp:Label ID="Label1" runat="server" Text='<%# Bind("CategoryName") %>'></asp:Label></a>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="Description" HeaderText="Description"
                    SortExpression="Description" />
            </Columns>
            <FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
            <HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
            <PagerStyle BackColor="#FFCC66" ForeColor="#333333" HorizontalAlign="Center" />
            <RowStyle BackColor="#FFFBD6" ForeColor="#333333" />
            <SelectedRowStyle BackColor="#FFCC66" Font-Bold="True" ForeColor="Navy" />
        </asp:GridView>

As you can see, the Item Template for Category Name is modified to sport a hyperlink to “Categories” page followed by the CategoryName itself.  This would mean that the URL for a category, say Beverages would point to Categories/Beverages

Similarly, on the Categories page, I added a GridView and configured it to use the “Allphabetical List of Products” Table.  I also modified the Bound field for ProductName to a template column to have a link to another Products Page.  The modified GridView code looks as below:-

<asp:GridView ID="GridView1" runat="server" AllowPaging="True"
           AllowSorting="True" AutoGenerateColumns="False" CellPadding="4"
           DataSourceID="SqlDataSource1" ForeColor="#333333" GridLines="None">
           <AlternatingRowStyle BackColor="White" />
           <Columns>
               <asp:TemplateField HeaderText="CategoryName" SortExpression="CategoryName">
                   <ItemTemplate>
                     
<a href="Products/<%# Eval("ProductName") %>"><asp:Label ID="Label1" runat="server" Text='<%# Bind("ProductName") %>'></asp:Label></a>
                   </ItemTemplate>
               </asp:TemplateField>
               <asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit"
                   SortExpression="QuantityPerUnit" />
               <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
                   SortExpression="UnitPrice" />
               <asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock"
                   SortExpression="UnitsInStock" />
               <asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder"
                   SortExpression="UnitsOnOrder" />
               <asp:BoundField DataField="ReorderLevel" HeaderText="ReorderLevel"
                   SortExpression="ReorderLevel" />
               <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
                   SortExpression="Discontinued" />
           </Columns>
           <EditRowStyle BackColor="#2461BF" />
           <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
           <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
           <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
           <RowStyle BackColor="#EFF3FB" />
           <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
       </asp:GridView>

Note, while configuring above GridView, in the screen where we configure DataSource, I also added a where condition to accomodate the Route Request.  The screen looks as below:-

confscreen1

confscreen2

Note that I had selected the Where condition from the first screen and specified “CategoryName” under Column,“=” under Operator and “Route” under Source.  Also specified are the RouteKey “catname” and DefaultValue “Beverages”.  Post this, I just had to click on “Add” and then “Ok” to get a conditional select statement in the SQL DataSource (note: for the purpose of this demo, I have used SQL DataSource.  But this would work even if you used any other datasource type / written ADO.NET Code).  The “Route” type is new feature added under Source in Visual Studio 2010.

Once the above configuration is done, the SQL DataSource code looks as below:-

<asp:SqlDataSource ID="SqlDataSource1" runat="server"
           ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
           SelectCommand="SELECT [ProductName], [QuantityPerUnit], [UnitPrice], [UnitsInStock], [UnitsOnOrder], [ReorderLevel], [Discontinued] FROM [Alphabetical list of products] WHERE ([CategoryName] LIKE '%' + @CategoryName + '%')">
          
<SelectParameters>
               <asp:RouteParameter DefaultValue="Beverages" Name="CategoryName"
                   RouteKey="catname" Type="String" />
           </SelectParameters>
       </asp:SqlDataSource>

I have also added a label to the page just to show the term used to filter and the value for that can be picked up from the Page.RouteData values in the codebehind as follows:-

protected void Page_Load(object sender, EventArgs e)
       {
           if (Page.RouteData.Values["catname"] != null)
           {
               lblDisplay.Text += "<b>" + Page.RouteData.Values["catname"].ToString() + "</b>";
           }
           else
           {
               lblDisplay.Visible = false;
           }
       }

Before getting into Route Configuration, I also added a DetailsView control in the Products.aspx page to show the complete details of a product.   And when configuring the DataSource for the DetailsView, I again specified the WHERE condition to the picked up from the RouteData that would come from the above GridView in Catagories Page.

Once this is done, all that is pending is to configure the Route Values.  In .NET 3.5 SP1 if you want to establish routing, you would have to manually create the WebFormRouteHandler Class and make sure all the pages inherit from this class.  However, in .NET 4.0, it has been much simplied.  All I had to do was open the Global.asax and add the following

protected void Application_Start(object sender, EventArgs e)
        {
             RouteTable.Routes.Add("ProductRoute", new Route("Categories/Products/{productname}",
       new PageRouteHandler("~/Products.aspx")));

            RouteTable.Routes.Add("CategoryRoute", new Route("Categories/{catname}",
       new PageRouteHandler("~/Categories.aspx")));
        }

(note you would need to add System.Web.Routing namespace to be able to use PageRouteHandler, RouteTable classes etc.,)

So, in the Default.aspx page, all the Catagories would have a link that points to /Categories/<CategoryName> and in the Categories.aspx page, all the ProductNames would have a link that points to /Categories/Products/<ProductName>

A typical URL is http://localhost/Categories/Condiments and http://localhost/Categories/Products/Aniseed%20Syrup

Note that similarly, we have close to 10 URLs for Beverages and around 80 URLs (a URL for each product as above) for Products in this particular application.

You can download the sample from  (Add your connectionstring to Northwind Database in the web.config file)

Cheers !!!

posted @ Thursday, August 20, 2009 7:21 AM

Print

Comments on this entry:

# re: What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

Left by Shail at 8/20/2009 9:12 AM
Gravatar
Nice one,
Keep on writing :)

One question, is there any way in forthcoming release of ASP.net where I can encrypt entire URL or some part of it, so that it will be less hackable. Atleast the "QueryString" part. like
htp://www.localhost.com/products.aspx?jsafhsjdfrr454543ksdfkdsafjdsf

But still the parameters will be available to my ASP.Net controls.I hope I am not too demanding

Shail

# re: What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

Left by Scott Galloway at 8/20/2009 11:58 AM
Gravatar
Shail, not 'built in' but it's pretty easy to achieve that...

# re: What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

Left by CodeDigest at 8/20/2009 9:54 PM
Gravatar
Cool!! This is really good!!!

# re: What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

Left by chandradev at 8/21/2009 12:54 AM
Gravatar
nice article

# re: What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

Left by rtpHarry at 8/21/2009 5:46 AM
Gravatar
I am not a rockstar developer so I dont know if this is reasonable request but I always cringe when I see strings instead of strongly typed data.

Obviously this has been thought about as the people behind asp.net are top quality developers but is there a reason why there is so much code like Page.RouteData.Values["catname"] throughout the platform?

Doesn't it break the DRY principle by spreading this out over the project? And its something that the compiler cant catch.

Still the feature itself is great, thanks for the post!


@Shail - If you did that then please take into account the SEO aspect that Google needs to able to see consistent urls to your pages if you want them indexing.



# re: What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

Left by Vik at 8/21/2009 7:06 AM
Gravatar
@rtpHarry - Strongly typed is good but can't be assigned to at runtime. In case of Page.RouteData.Values["catname"] you can change "catname" to anything at runtime..

# re: What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

Left by Shail at 8/22/2009 2:59 AM
Gravatar
@rtpHarry
Well I need that for my In House Web site, Which is not going to be exposed to world.
My ideas is that I should write an HTTPModule for pre and pots Encryption and Decrption.

@Scott, can you give some suggestions for that ?

# re: What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

Left by Jon at 8/23/2009 4:05 PM
Gravatar
Excellent stuff, another reason not to pick up that book on MVC I just bought....

# re: What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

Left by web development company at 8/27/2009 11:48 AM
Gravatar
the new asp 4.0 has may new fetures and I'll be happy to read more about it , so please post us if you have any more of these examples

# re: What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

Left by rtpHarry at 8/29/2009 7:53 AM
Gravatar
@Vik - the fact that it can be changed in this way is my problem. If you put put "catnames" instead of "catname" nobody is going to know until your website crashes.

An alternative would be to strongly type it into:
Page.RouteData.Values.CatName

I dont know if there are some situations where you would absolutely have to access it via ["catname"]? If there are I guess you could leave that in and also strongly type for day-to-day use.

# re: What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

Left by ertan at 9/6/2009 6:53 AM
Gravatar
ASP.NET fastly evolving technology. I am waiting asp.net 4 with exciting.
thanks.

# re: What's new in ASP.NET 4.0 - Part II - Routing in Webforms

Left by Prodis at 9/8/2009 3:23 PM
Gravatar
Oh, gosh!
One more article with a lot of infrastructure code at interface. One more article for "drag-and-dropers" programmers.
I am sorry for them.

# re: What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

Left by vikrant at 9/20/2009 4:42 PM
Gravatar
Nice one

It's really great post for developer who want their website to be more SEO optimized

# re: What’s new in ASP.NET 4.0 – Part II – Routing in Webforms

Left by Christian Louboutin at 11/20/2009 11:43 PM
Gravatar
Once upon a time, two women created the cutest velour hoodies and matching drawstring pants. The line was called Christian Louboutin and every starlet in Tinseltown had to have one. Soon after, so did the rest of the world. Now the once little brand has blossomed into a fashion empire, complete with clothing, Christian Louboutin Shoes, jewelry, handbags, and most recently, fragrance.

Your comment:



 (will not be displayed)


 
 
 
 
 

Live Comment Preview:

 
«November»
SunMonTueWedThuFriSat
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345