.Net ramblings
# Thursday, 03 February 2005
An ISAPI Filter to have nice URLs for your Asp.Net site

Background

My content management system stores all the pages in a sql database, so if you go to /home.html, there is no document by that name on the server.  Instead, i have one .aspx page called content.aspx that handles every request dynamically and it outputs the content for the page.

You can partially achieve this same effect without using an ISAPI filter (see http://www.codeproject.com/aspnet/URLRewriter.asp) but you don't get the advantage of specifying a folder path as a valid url.  For example, if you request /Departments/HR/ then you will get a 404 on the server, because IIS doesn't know to pass on this request to my /content.aspx page.  Jakob Nielsen (the usability expert) says that hackable urls are important, i.e. users should be allowed to remove parts of the path of the page they are at, and arrive at a level higher up in the site.  The ISAPI filter used here allows this.

Requirements for the Filter

  • Every .html request should be forwarded to /content.aspx
  • Every default document request should be forwarded to /content.aspx
  • A request with a querystring (?) should not be redirected because it is assumed to be a dynamic page.
  • The IIS log should record the original url (i.e. /Home.html) instead of /content.aspx?Url=/home.html

Because the code is in C++ and there is a lot of messy error checking stuff going on all over the place, i won't post it here (mess up my blog). instead you can download the VS 2003 solution (20 k) with source files + executable, and examine it for yourself if you're interested.  It does work, and i have about 15 sites runnning off this filter for a long time now. 

Credits

This solution is 95% taken from David Wang's excellent post on the ISAPI-DEV ms newsgroup. I just added in support for default documents and ignoring dynamic page requests.


Thursday, 03 February 2005 12:14:02 (GMT Standard Time, UTC+00:00)  #    Comments [2]  Asp.Net

Thursday, 31 March 2005 19:20:03 (GMT Daylight Time, UTC+01:00)
Tim,

Did a quick code review on your ISAPI Filter and it does not take into
account that a directory may contain an ".html" in it. If the Http Request
URL is:
/folder1/folder2.html/page.aspx
your filter will redirect this Http Request when in fact it should not.

<Problem>
// Check the URL for the triggered extension
htmlDocument = strstr(AQ_URL, AQ_File_Extension);
</Problem>

<Solution>
// Check the URL for the triggered extension
if( (htmlDocument = strstr(AQ_URL, AQ_File_Extension)) != NULL )
{
if( lstrlen(htmlDocument) > lstrlen(AQ_File_Extension) )
htmlDocument = NULL;
}
</Solution>

Just a heads up!

Tiago Halm
Tiago Halm
Thursday, 31 March 2005 22:06:20 (GMT Daylight Time, UTC+01:00)
hi Tiago,
thanks a million for pointing that out. i went through the code again myself and found a tighter way of specifying the intercept conditions. i dug out a 'strrstr' c function to get the last index of a substring, which is useful in thise case.
i modified your version slightly to suit the conditions i think are appropriate. the download zip file has been updated.
thanks again.
tim.

code update:

lastSlash = strrchr(url, '/');

if(strrstr(url, ".aspx") > lastSlash) // bail, ignore requests ending in /something.aspx
return SF_STATUS_REQ_NEXT_NOTIFICATION;

if(strstr(url, ".asmx") > lastSlash) // bail, ignore requests ending in /something.asmx
return SF_STATUS_REQ_NEXT_NOTIFICATION;

// Check the URL for the triggered extension in the page part of the url.
// get the pointer to the .html (if it exists)
htmlDocument = strrstr(url, htmlExtension);
if(htmlDocument != NULL) // a html request requires that the last forward slash comes before the .html
isHtmlDocument = (lastSlash < strrstr(url, htmlExtension));

// also check for default document request
if(!isHtmlDocument)
isDefaultDocument = (strrchr(lastSlash, '.')) ? false : true;
OpenID
Please login with either your OpenID above, or your details below.
Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, strike) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

[Captcha]Enter the code shown (prevents robots):

Live Comment Preview