The conception, birth, and first steps of an application named Charlie

Subscribe: Atom or RSS

Charlie has Cool URLs - Part 4

by Alister Jones (SomeNewKid)

I lied to you earlier. It was a white lie, with no harm intended. But it was a lie nonetheless, and for that I’m sorry. If I explain, will you forgive me?

In my first and second look at Charlie’s URLs, I said that Charlie uses a slight-of-hand to add the .aspx extension to any incoming URL that has no extension, and that the Web.config file has been updated so that any request with an .aspx extension gets handled by the PageBuilder class. This process is indeed what happens, but it is not an .aspx extension that Charlie uses to route page requests to its PageBuilder class. Rather, it is a custom .asxx extension, because I wanted to leave the built-in .aspx extension untouched. Let’s see why.

Toward the end of my second weblog entry on cool URLs, we saw the following diagram.

Consider that a website is presenting a weblog entry, and within that weblog entry is a photo of Pamela Anderson before she was attacked by a bicycle pump. The URL for that photo may be the following:

/weblog/2006/apr/14/a-rare-photo-indeed.jpg

If you look at the diagram above, you will see that the request will be handled by Charlie’s own JPEG Handler. The JPEG Handler will just pick up the .jpg file and return it, which is all we want it to do.

Consider now a website that is presenting a photographer’s photo gallery, and within that gallery is a photo of the exquisite Michelle Pfeiffer. The URL for that photo may be the following:

/photos/celebrities/michelle-pfeiffer/batman-premiere.jpg

If you recall that Charlie uses a fall-through approach of matching URLs with plugins, you will see that the above URL may be associated with the PhotoGallery plugin. And here is where it gets interesting.

Most plugins do not care about requests for GIF images and JPEG photos, so they will not want to handle such requests. These plugins will simply let the request go through to the Charlie’s own designated handler (see the diagram above).

Some plugins, however, do care about requests for GIF images and JPEG photos. There plugins will want to handle such requests themselves, rather than allowing the request to go through to Charlie’s own default handlers. The PhotoGallery plugin, for example, may wish to present the .jpg image not by itself, but on a page with an attractive border, a title, and a copyright notice. The PhotoGallery plugin may also wish to record how many times a particular photo has been viewed. Put simply, the PhotoGallery plugin should be able to do whatever it likes with requests for photos.

So, how can we update Charlie so that a plugin can take control of a request if it wants control, but otherwise allow a request to flow through to the default handlers? If we look at again at the diagram above, we see an ideal point at which we can do this.

At the point indicated, all authentication and authorization checks have been performed, but the handler has not yet been chosen. This is the point at which Charlie says to the Plugin associated with the request, “Hey buddy, if you want to handle this request yourself, tell me now, otherwise I’ll handle it myself.” The way Charlie does this is by giving the associated Plugin the current WebContext object, which allows the Plugin to do whatever it likes to the HttpContext, HttpRequest, and HttpResponse objects it holds. The PhotoGallery plugin can therefore “catch” any JPEG requests, and re-route them to its own handler. Here is a simple example:

public void FilterWebContext(WebContext webContext)
{
    if (webContext.WebRequest.Address.Extension == "jpg")
    {
        String handler = "~/plugins/photogallery/jpgHandler.aspx";
        webContext.HttpContext.RewritePath(handler);
    }
}

There’s quite a bit wrong with the above code example, but it gives the basic idea of how Charlie allows its own plugins to update the above diagram in the following way.

This explains why I wanted to leave the .aspx extension untouched. If a plugin wishes, it can redirect an incoming request to one of its own .aspx pages, in which case ASP.NET’s own PageHandlerFactory takes control of loading up the .aspx page and any code-behind file. Charlie’s own PageBuilder class is associated only with the custom .asxx extension that Charlie adds to any request that does not otherwise have an extension.

What was particularly nice here is that updating Charlie to allow plugins to “take control” of an incoming request was a further example of emergence. The existing Web System and Plugin System presented the fertile soil from which this new feature could be grown. No part of Charlie’s architecture or design had to be changed or fudged in any way. The solution emerged naturally from its existing architecture and existing design. I am not patting myself on the back here. I am sharing the lesson that I am learning again and again: a little bit of object-oriented design goes a long, long way.

This weblog entry concludes the look at Charlie’s cool URLs, and how those URLs tie in with Charlie and its plugins.

by Alister Jones | Next up: Story Time

2 comments

______
Anonymous Anonymous said...  
 

The article is a bit too clever, clever - some actual code examples would be nice rather than rattling on about Charlie all the time...

______
Blogger Alister said...  
 

I am not trying to be clever; I am trying to be different. There are already thousands of weblogs sharing code snippets. As I have said earlier, I am trying to focus on the “why” of development, leaving the other weblogs to focus on the “how”.

Do I rattle on about Charlie all the time? Of course I do—it is the title and the theme of this weblog.

I am just trying to do something a little bit different. If I succeed, great. If I do not succeed, so be it.

Post a Comment

----