Saturday, March 19, 2011

Routing in ASP.NET 4

ASP.NET 4 adds built-in support for using routing with Web Forms. Routing lets you configure an application to accept request URLs that do not map to physical files. Instead, you can use routing to define URLs that are meaningful to users and that can help with search-engine optimization (SEO) for your application. For example, the URL for a page that displays product categories in an existing application might look like the following example:
http://website/products.aspx?categoryid=12 
By using routing, you can configure the application to accept the following URL to render the same information:
http://website/products/software 
Routing has been available starting with ASP.NET 3.5 SP1. (For an example of how to use routing in ASP.NET 3.5 SP1, see the entry Using Routing With WebForms on Phil Haack's blog.) However, ASP.NET 4 includes some features that make it easier to use routing, including the following:
  • The PageRouteHandler class, which is a simple HTTP handler that you use when you define routes. The class passes data to the page that the request is routed to.
  • The new properties HttpRequest.RequestContext and Page.RouteData (which is a proxy for the HttpRequest.RequestContext.RouteData object). These properties make it easier to access information that is passed from the route.
  • The following new expression builders, which are defined in System.Web.Compilation.RouteUrlExpressionBuilder and System.Web.Compilation.RouteValueExpressionBuilder:
  • RouteUrl, which provides a simple way to create a URL that corresponds to a route URL within an ASP.NET server control.
  • RouteValue, which provides a simple way to extract information from the RouteContext object.
  • The RouteParameter class, which makes it easier to pass data contained in a RouteContext object to a query for a data source control (similar to FormParameter).

Routing for Web Forms Pages

The following example shows how to define a Web Forms route by using the new MapPageRoute method of the Route class:
public class Global : System.Web.HttpApplication 
{ 
  void Application_Start(object sender, EventArgs e) 
  { 
    RouteTable.Routes.MapPageRoute("SearchRoute", 
      "search/{searchterm}", "~/search.aspx"); 
    RouteTable.Routes.MapPageRoute("UserRoute", 
      "users/{username}", "~/users.aspx"); 
  } 
} 
ASP.NET 4 introduces the MapPageRoute method. The following example is equivalent to the SearchRoute definition shown in the previous example, but uses the PageRouteHandler class.
RouteTable.Routes.Add("SearchRoute", new Route("search/{searchterm}", 
  new PageRouteHandler("~/search.aspx"))); 
The code in the example maps the route to a physical page (in the first route, to ~/search.aspx). The first route definition also specifies that the parameter named searchterm should be extracted from the URL and passed to the page.
The MapPageRoute method supports the following method overloads:
  • MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess)
  • MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults)
  • MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints)
The checkPhysicalUrlAccess parameter specifies whether the route should check the security permissions for the physical page being routed to (in this case, search.aspx) and the permissions on the incoming URL (in this case, search/{searchterm}). If the value of checkPhysicalUrlAccess is false, only the permissions of the incoming URL will be checked. These permissions are defined in the Web.config file using settings such as the following:
<configuration> 
  <location path="search.aspx"> 
    <system.web> 
      <authorization> 
        <allow roles="admin"/> 
        <deny users="*"/> 
      </authorization> 
    </system.web> 
  </location> 
  <location path="search"> 
    <system.web> 
      <authorization> 
        <allow users="*"/> 
      </authorization> 
    </system.web> 
  </location> 
 
</configuration> 
 
In the example configuration, access is denied to the physical page search.aspx for all users except those who are in the admin role. When the checkPhysicalUrlAccess parameter is set to true (which is its default value), only admin users are allowed to access the URL /search/{searchterm}, because the physical page search.aspx is restricted to users in that role. If checkPhysicalUrlAccess is set to false and the site is configured as shown in the previous example, all authenticated users are allowed to access the URL /search/{searchterm}.

Reading Routing Information in a Web Forms Page

In the code of the Web Forms physical page, you can access the information that routing has extracted from the URL (or other information that another object has added to the RouteData object) by using two new properties: HttpRequest.RequestContext and Page.RouteData. (Page.RouteData wraps HttpRequest.RequestContext.RouteData.) The following example shows how to use Page.RouteData.
protected void Page_Load(object sender, EventArgs e) 
{ 
  string searchterm = Page.RouteData.Values["searchterm"] as string; 
  label1.Text = searchterm; 
} 
 
The code extracts the value that was passed for the searchterm parameter, as defined in the example route earlier. Consider the following request URL:
http://localhost/search/scott/ 
When this request is made, the word "scott" would be rendered in the search.aspx page.

Accessing Routing Information in Markup

The method described in the previous section shows how to get route data in code in a Web Forms page. You can also use expressions in markup that give you access to the same information. Expression builders are a powerful and elegant way to work with declarative code. (For more information, see the entry Express Yourself With Custom Expression Builders on Phil Haack's blog.)
ASP.NET 4 includes two new expression builders for Web Forms routing. The following example shows how to use them.
<asp:HyperLink ID="HyperLink1" runat="server" 
  NavigateUrl="<%$RouteUrl:SearchTerm=scott%>">Search for Scott</asp:HyperLink> 
 
In the example, the RouteUrl expression is used to define a URL that is based on a route parameter. This saves you from having to hard-code the complete URL into the markup, and lets you change the URL structure later without requiring any change to this link.
Based on the route defined earlier, this markup generates the following URL:
http://localhost/search/scott
ASP.NET automatically works out the correct route (that is, it generates the correct URL) based on the input parameters. You can also include a route name in the expression, which lets you specify a route to use.
The following example shows how to use the RouteValue expression.
<asp:Label ID="Label1" runat="server" Text="<%$RouteValue:SearchTerm%>" />
When the page that contains this control runs, the value "scott" is displayed in the label.
The RouteValue expression makes it simple to use route data in markup, and it avoids having to work with the more complex Page.RouteData["x"] syntax in markup.

Using Route Data for Data Source Control Parameters

The RouteParameter class lets you specify route data as a parameter value for queries in a data source control. It works much like the class, as shown in the following example:
<asp:sqldatasource id="SqlDataSource1" runat="server" 
    connectionstring="<%$ ConnectionStrings:MyNorthwind %>" 
    selectcommand="SELECT CompanyName,ShipperID FROM Shippers where 
      CompanyName=@companyname" 
  <selectparameters> 
    <asp:routeparameter name="companyname" RouteKey="searchterm" /> 
  </selectparameters> 
 
</asp:sqldatasource>  
 
In this case, the value of the route parameter searchterm will be used for the @companyname parameter in the Select statement

No comments:

Popular Posts