links for 2010-03-10

by Dan@Delicious 11. March 2010 05:07

Tags:

ASP.NET 4.0 Part 11, Configuring Routing Is Easier

by DanM 10. March 2010 01:00

Welcome to part 11 of my tour through ASP.NET 4.0. In this episode, we're going to take a look at how routing for webforms has been made easier to set up in ASP.NET 4.0. This will be followed up in Part 12 with a look at the new route-aware classes, methods and properties in more detail.

Routing was originally introduced in ASP.NET 3.5 SP1 as part of the foundations to enable the ASP.NET MVC template engine to work. It could also be used against the webforms engine but a certain amount of rolling-your-own-foundation coding was required to enable it properly.

In ASP.NET 4.0, that initial legwork is no longer necessary as routing for webforms is now supported as standard in System.Web, the majority of the configuration for routing is pre-set in system-wide config files, and some extra goodness has been added into various classes for ease of use as well. All in all, if you haven't had occasion to try routing with webforms before, try it with ASP.NET 4.0. It's really simple.

Why?

There are a metric / boatload / of articles introducing routing and how it works. In a nutshell, routing, like URL rewriting, is a response to two general criticisms of websites.

  1. We humans prefer it if a page's URL is readable. For example, http://myforums.info/forum-Music is easier to read than http://myforums.info/forum.aspx?id=2. It's easier to remember too
  2. Search engines prefer human-readable URLs as well. In particular, they like URLs with no querystring parameters at the end. And, the more search engine friendly a site's URLs are, the better indexed they may be by a search engine and the higher they may appear in search rankings. (Obviously, URLs aren't the only thing indexing robots look at when they come to your site - Descriptions and Keywords are up there with a host of other things too - but they certainly help.)

So then, the major consequence of routing as far as webforms is concerned are URLs which are more readable for humans and search robots alike with no reduction of information to the page itself.

How?

Routes are initialized as named, regular expressions (using a subset of the standard .NET RegEx syntax) and given an order in which they will be matched against the currently requested URL. For example,

  1. user-{username}
  2. forum-{forumname}
  3. forum-{forumname}/thread-{threadid}

Let's say a request comes to the server for http://myforums.info/forum-Music.

  • If the request is for a page that actually exists on the site, no routing actually occurs and that page is loaded and runs as normal.
  • If the page doesn't exist, the requested URL is matched against each initialized route in the order you've specified. In this example, user-{username} doesn't match the requested URL, so the next route is tried.
  • When a route matching the requested URL is found, the request is routed to the page that deals with that route. Any named sections of the route are then made available to the handling page within the RouteData collection. For example, http://myforums.info/forum-Music matches forum-{forumname}, so control for the request would be passed to the page for that route along with a RouteData collection containing one KeyValuePair where forumname is the Key and Music is its value.
  • If no route is found to match the incoming request, it is passed to the standard ASP.NET 404 page or a custom page if you've defined one.

Routing Is Neither URL Rewriting nor Redirection

Hopefully, the above description should differentiate routing from URL rewriting and page redirection. However, just in case it didn't...

  • Routing is not Page Redirection
    Redirection can only work if the incoming URL is for a page that exist. It works by sending a response to the browser saying that the page has moved with the browser then issuing a second request for the URL it is being redirected to. Routed URLs on the other hand do not necessarily refer to a page that actually exists - they will often seem to refer to directories for example - and are dealt with in one request. Browsers will not issue a second request for the actual page which handles the route.
  • Routing is not URL Rewriting
    URL rewriting occurs very early on in the asp.net request pipeline, literally as request processing is beginning. When the rewritten URL is resolved, IIS then sends it down the pipeline to find a handler to deal with it. It has no control over what handler deals with the request. Routing, on the other hand, occurs further down the pipeline, once the request has been authorised, at which point the routing module dispatches the request to a handler based on which route the request matches and the handler specified by you to deal with the route. (IIS team member Ruslan Yarushev goes into much more detail on the differences between the two in this article.)

Setting Up Webforms Routing In ASP.NET 3.5

Briefly, here are the steps needed to enable routing for webforms in ASP.NET 3.5.

  1. All routing classes and namespaces are found in a new DLL, System.Web.Routing.dll to be included as a reference in your website.
  2. The UrlRoutingModule needs to be added to the list of modules enabled for the site in web.config (as described here in MSDN)
  3. A handler class inheriting IRouteHandler needs to be created that understands how to resolve the route into the page or handler that will actually process the request and generate the RouteData collection. Both Phil Haack and Chris Cavanagh put forward basic implementations of this handler, discussing potential security issues.
  4. Register the routes for the site in the Application_Start handler of global.asax using your new route handler class. For example,
protected void Application_Start(object sender, EventArgs e)
{
 RegisterRoutes(RouteTable.Routes);
}

public static void RegisterRoutes(RouteCollection routes)
{
 // Route existing files (default will shortcut routing if physical file exists)
 RouteTable.Routes.RouteExistingFiles = true;

 // Add StopRoutingHandler for .axd and .asmx requests
 routes.Add(new Route("{resource}.axd/{*pathInfo}", 
              new StopRoutingHandler()));
 routes.Add(new Route("{service}.asmx/{*pathInfo}", 
              new StopRoutingHandler()));

 // Add existing routes
 routes.Add("Users", new Route("user-{username}", 
              new WebFormRouteHandler("~/users.aspx", true)));
 routes.Add("Forums", new Route("forum-{forumname}", 
              new WebFormRouteHandler("~/forum.aspx", true)));
 routes.Add("Threads", new Route("forum-{forumname}/thread-{threadid}", 
              new WebFormRouteHandler("~/thread.aspx", true)));

 // Add an unnamed handler for all unknown requests (now created in the PageRoute table)
 //routes.Add(new Route("{value}", 
                new WebFormRouteHandler("~/pages/default.aspx")));
}
  1. Write your pages as you would normally using the RouteData collection in place of the Querystring class. You'll need to make RouteData available by passing a RequestContext object to the object that needs access to the RouteData. Again, Phil Haack suggests one way of doing this (via an IRoutableObject interface) here.
  2. Finally, you have to configure IIS to have ASP.NET deal with requests to your routes, thus passing them on to your RouteHandler classes. If you're using IIS6 and your routes are extension-less (i.e. missing .aspx, .asmx , .ashx etc file extensions in their composition), you'll need to configure wildcard maps on a per-directory level according to where your routes point else you'll end up serving all your static files with ASP.NET as well. Full instructions for this come courtesy of Steve Sanderson (Part 1, Part 2).

Setting Up Webforms Routing In ASP.NET 4.0

By comparison, the procedure is far more straightforward in ASP.NET 4.0, thanks in large part to Microsoft being able to open up and edit System.Web and the classes inside it. Let's compare

  1. System.Web.Routing has been folded into System.Web.dll in .NET 4.0 so there is no need for an additional reference to it in your solution.
  2. The UrlRoutingModule is also already set up in the machine-wide web.config file which means that it works straight off the bat in IIS 6. For IIS 7 users, however, you'll need to enable it with the following addition to web.config.
<?xml version="1.0"?>
<configuration>
...
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      ...
    </modules>
  </system.webServer>
</configuration>
  1. ASP.NET 4.0 includes an implementation of IRouteHandler for you to use - it's called PageRouteHandler. There's no reason why you can't build your own as before, but it's no longer necessary.
  2. You still need to register routes for your application but if you're using the built-in PageRouteHandler class, you can use the MapPageRoute helper method to make route registration clearer.
protected void Application_Start(object sender, EventArgs e)
{
  RegisterRoutes(RouteTable.Routes);
}

public static void RegisterRoutes(RouteCollection routes)
{
  // Route existing files (default will shortcut routing if physical file exists)
  RouteTable.Routes.RouteExistingFiles = true;

  // Add StopRoutingHandler for .axd and .asmx requests
  routes.Add(new Route("{resource}.axd/{*pathInfo}", 
              new StopRoutingHandler()));
  routes.Add(new Route("{service}.asmx/{*pathInfo}", 
              new StopRoutingHandler()));

  // Add existing routes with MapPageRoute helper method
  routes.MapPageRoute("Users", "user-{username}", "~/users.aspx");
  routes.MapPageRoute("Forums", "forum-{forumname}", "~/forum.aspx", true);

  // MapPageRoute is equivalent to adding a Route with the PageRouteHandler like so
  routes.Add("Threads", new Route("forum-{forumname}/thread-{threadid}", 
    new PageRouteHandler("~/thread.aspx", true)));
}
  1. Any pages you write now automatically have access to the RouteData collection as a property of the Page class itself, as well as several other route-aware additions we'll review in the next section.
protected void Page_Load(object sender, EventArgs e)
{
  lblHello.Text = 
    RouteData.Values["username"] == null ?
      "Hello Mr A. Nonymous" : 
      String.Format("Hello {0}", RouteData.Values["username"].ToString());
}
  1. Regrettably, while integration into IIS7 Integrated Mode remains quite simple, you still need to configure IIS6 \ IIS7 in Classic mode to associate the routes used in your site with ASP.NET as you did in ASP.NET 3.5. That's a failing of IIS6 rather than ASP.NET.

As you can see, setting up routing for an ASP.NET 4.0 webforms site is somewhat simpler than for the previous version as Microsoft has taken the opportunity to refactor routing into the core ASP.NET framework. In the next episode, we'll look at several of the new route-aware features for use once in ASP.NET 4.0 sites we've set routing up. Until then, happy coding!

Filmdash 2010

by DanM 8. March 2010 23:00

This year's Filmdash event took place last weekend in anticipation of The Oscars. This is the rather manic weekend where teams of budding film makers get given the name and theme of a film to make from scratch in 48 hours and don't usually sleep that much. I've done it before but couldn't make it this year. Happily however, Messrs Squier and Eaves carried on regardless and put together the comic Silence is Gordon. And a little making of... video too. The Oscars may still be far away but damn it's fun to make films. Well done lads!

Silence Is Gordon

ASP.NET 4.0 Part 10, A Handful Of Little Things

by DanM 4. March 2010 22:00

Welcome to part 10 of my tour through ASP.NET 4.0. In this episode, we’re going to look at a few small but useful additions to the ASP.NET 4.0 webforms template engine before we head out into the wider world of the core framework – routing, caching, sessions and so on.

<asp:Chart> Now Built In

1_chart We’ve seen before how Microsoft has folded features from ASP.NET 3.x and other out-of-band releases into the core ASP.NET 4.0 DLLs before. Case in point, the ASP.NET Chart control released in November 2008. This was based on Dundas Chart source code version 5.5 via a Microsoft security, accessibility, and API review. It’s now built into the core which means no additional web.config to get it running and an entry in the Data tab of the standard toolbox set.

Check out more info on the charting control here.

Three New Redirect Methods

The HttpResponse class has been fitted with three new redirect methods, two to work nicely with routing, which we’ll cover later in this series, and the other to play nicer with search engines. Response.RedirectToRoute and Response.RedirectToRoutePermanent are the two we'll note in passing for now. As you might suspect, these allow us to redirect users to a page at the end of a route we've defined rather than the page directly. The main difference between the two is that RedirectToRoute sends a HTTP 302 Found response back to the browser while ResponseToRoutePermanent sends a HTTP 301 Moved Permanently. To a user, both methods simply redirect their browser to a new page. To a search engine spider, 302 Found implies that the page has moved temporarily, so it will index both the old and new, temporary location. 301 Moved Permanently implies that henceforth the old location is not used and it will only index the new location going forward. 

The third new redirect method, Response.RedirectPermanent, also sends a 301 Move Permanently response, but redirects straight to a page rather than a route. It has two overloads like Response.Redirect.

  • RedirectPermanent(string url)
  • RedirectPermanent(string url, bool endResponse)

The first parameter is simply the URL of the page you wish to redirect to.

Response.RedirectPermanent(http://www.danmaharry.com);

The second parameter lets you specify whether or not ASP.NET should stop processing the page and move straight to processing the Application_EndRequest method in global.asax.cs if you have one.

Side note: There has always been an issue with Response.Redirect because it calls Response.End internally which can lead to ASP.NET silently throwing ThreadAbortExceptions. A good thread on this problem can be found here. The same is likely true of Response.RedirectPermanent, so the upshot is you might want to use these lines of code to avoid the exception being thrown although there are more thorough solutions on offer.

Response.RedirectPermanent("http://www.danmaharry.com", false);
HttpContext.Current.ApplicationInstance.CompleteRequest();  

Your mileage may vary with each approach.

Inline HTML Encoded Strings

Script injection is one of those attack vectors on a website which is easily missed if you're not careful and has the potential for a great deal of grief if you do forget. A first guard against this is to HTMLEncode any user input before being stored in the database or shown on screen. Typically this all done in the code-behind, but the latter can now also be achieved inline using the new <%: message %> syntax, which will automatically HTML encode the given message string. For example,

<p>Unencoded : <script type='text/javascript'>alert('hello');</script></p>
<p>Encoded : <%:"<script type='text/javascript'>alert('hello');</script>" %></p> 

The top line will have the browser running the javascript in the script tags. The bottom line will HTMLEncode the script tags and produce the following code (on one line - the line returns are for clarity).

<p>Encoded : 
  &lt;script type=&#39;text/javascript&#39;&gt;alert(&#39;hello&#39;);&lt;/script&gt; 
</p>

Take care not to HTMLEncode a string in code-behind and then also inline with this syntax. ASP.NET will simply HTMLEncode it twice - probably not what you need.

Side note: Two other items of import with respect to ASP.NET security have happened recently.

That's all for today. In the next episode, we'll take a look at Routing for Webforms. Happy coding!

UK Events Of Interest (March\April 2010)

by DanM 3. March 2010 17:00

Scott Guthrie is coming to the UK for two days. He’ll be in Glasgow and Birmingham on March 25 and 26 respectively. Registration opened today, so click quickly for Glasgow and Birmingham tickets before they are sold out. Both events are free.

If you can’t make either of those, Microsoft are running a week of tech days in London to mark the launch of Visual Studio 2010 and to promote the new Windows 7 Phone platform. They are all in the Vue 6 Cinema Broadway in Fulham. [ Twitter tweme: #TechDays ]

  • April 12 : Visual Studio 2010 – A Path to Big Ideas (for Heads of Development, Dev Managers and Software Architects
  • April 13 : Getting started with .NET Framework 4 and Visual Studio 2010 (for developers : wait list only)
  • April 14 : The Essential MIX – Highlights from MIX ‘10 with sessions on ASP.NET 4.0, Silverlight 4 and Azure (for developers)
  • April 15 : Best of Breed Client Applications on Windows 7 – Windows 7 API, Building Rich Clients with .NET 4 and a bit of Azure (for developers)
  • April 16 : Windows Phone – Developing for the Windows 7 Phones Series (for developers : registration not up yet)

If you’re a Silverlight fan, then Microsoft’s Silverlight Geek Jesse Liberty is doing a 9 day tour of UK with an extra in Dublin for those in Eire.

Overviews of the talks he’ll be giving can be found here on his blog.

Of course, if you’re in the US then you’ve also got MIX 10 (March 15-17), An Event Apart (April 5-7), the IA Summit 2010 (April 7-11), and Chirp : The Twitter Dev Conference (April 14 –15) to attend, so it’s not all bad really, is it?

Powered by BlogEngine.NET 1.6.0.0
Theme by Mads Kristensen, adapted by Dan Maharry

About Dan

Dan Maharry Dan Maharry
Web developer at Co-operative Web and tech writer. More...
Creative Commons License View Dan's bookmarks on Delicious LinkedIn Facebook Facebook Last.fm
Last.fm Twitter Subscribe to Dans RSS Feed Download Dans OPML File Add blog to technorati favorites

RecentComments

Comment RSS