Thursday, April 17, 2008

Semi-re-written URLs and the ~ resolver

I decided to try out using the PathInfo property of the HttpRequest class. Instead of the typical use of querystring vars

showthing.aspx?thingID=123

I thought I'd try out creating a friendlier URL such as

showthing.aspx/123

Instead of using the querystring to get the keyed values, I'd use the PathInfo collection instead. This in itself worked fine, however a small problem arises.

The app uses master pages and thus does some URL resolution for resources such as the CSS file. I've noticed over the years that sometimes the path will resolve to a root relative path:

/mysite/include/styles.css

and sometimes to a relative path:

../include/styles.css

I haven't found any way to control this behavior and I've wondered what determines it. Today I wondered if it might actually be somewhat sensible in that it will be resolved to the smallest result. For example if the resource is only 1 directory off, it might be resolved to a back reference (../???) whereas if it's a long was off (perhaps several directories back up) it will resolve to the root (/mysite/???). There doesn't seem to be a rhyme or reason to it.

The end result is that when I browse to my semi-re-written URL using path info data, the browser doesn't care that it's path info, so my CSS file reference ends up being something logically like this:

showthing.aspx/123/../include/styles.css

which resolves to

showthing.aspx/include/styles.css

which clearly isn't what I've intended.

If I can determine how to force the ~ resolution behavior to be root relative, then it will fix the problem. Otherwise, I can't use PathInfo and similarly I can't do any other kind of URL re-writing. :-( I suppose I could just make all my resource references root relative, but then I have to significantly change my development strategies. I tend to favor running in IIS (using virtual directories) for 2 reasons: 1) It's more realistic; 2) I work on some apps that consume web resources from other sites that I also run on my dev machine in IIS which is simpler than dealing with starting and managing 2 instances of Cassini.

Hopefully there's a way to force the behavior, otherwise it's back to query string vars.

2 comments:

robc said...

Hi Peter,

Interesting problem, and TBH, I can offer nothing in the way of the solution.

However, the path style looks very much like that of a RESTful website yes? Does looking at how RESTful websites are created using .NET offer any leads?

Peter Lanoie said...

I attended a user group presentation about the ASP.NET MVC framework. MVC makes use of "RESTfulness" to my understanding. I asked the presenter about how ASP.NET gets the requests from IIS as the URLs are not .aspx pages. He said that the application's configuration (web.config) handles this in IIS7 automatically. We have to manually create ISAPI mappings for IIS6.

That may all be irrelevant because I have no idea how RESTful apps are constructed in ASP.NET. But I guess my point in blabbering about the MVC is that I imagine they have some solution to the problem I describe. Simply making the resolved paths root relative instead of page relative should solve the problem. I'd be delighted to find that there already exists a setting for this.