Saturday, 09 April, 2005

It's been a while since I did a post on a programming topic so to break the drought I've decided to write a short article on how to make your ASP/ASP.Net applications "portable". What do I mean by portable? Well, I mean that you can comfortably switch your hosting platform from something like an Amiga to a Unix box without having to change your paths to the files.

If I were to start this site from scratch again the one thing I would do differently is to make sure the paths to all of the pages are platform independant. This is something that is fairly easy to achieve but the default configuration of most operating systems makes it more of pain than it should be. For example, Microsoft servers tend to use the extensions .asp and .aspx for pages that require some server side code. Apache servers tend to prefer the use of the PHP language to do server side processing and these pages end with a .php extension. While it possible to run php and asp using both Apache and IIS , each runs more smoothly with its language of choice.

The problem with these extensions is that if you decide one day that you'd like to move from using IIS to Apache, or visa-versa, you've got a serious pitfall if you want to make sure that links to your site from other people's blogs and what not will still work after the change. This is sort of a non-issue if you run you run your own server or if you're renting a dedicated server off some ISP - it's fairly easy on either platform to map .asp or .php to a different scripting engine. The real ball-ache comes when your web-space is on a shared host. Most companies that provide shared hosting only allow you FTP access to your space. They do not allow even the most rudimentary changes to the configuration of the web server.

So what can you do? Well, in ASP.NET at least, the best thing you can do is do a URL rewrite on all incoming requests on the site. So if a person goes to http://www.ckwop.me.uk/blog/111 you have an ASPX page that detects the 111 and then knows to pull the correct post out the database. This is actually a better design than my current set-up because some search engines are a bit funny about linking to pages that contain query strings. This also neatly satisfies the platform independance requirement too because this approach will allow us to use URLs of any format.

So how do you go about doing it? Well the best way to achieve this on the Microsoft platform (but not the easiest) is to map the ISAPI filter for ASP.NET application to all incoming requests. This can be done by mapping the ASP.NET dll to "*" (without the quotes). You then put a handler section in the web.config that points to a dll that handles all incoming requests. You do this by adding a key to the httpModule element under the System.Web section of the Web.Config. Take a look at the snippet below:

	<system.web>
		<httpModules>
			<add name="SomeModule" type="Ckwop.Web.SomeModule, Ckwop.Web" />
		</httpModules>
	<system.web>

The next step is to create a class called "SomeModule" in the assembly called "Ckwop.Web". This class should implement the IHttpModule interface. In the Init method on this class put a single line in that maps a method name to the BeginRequest event for the context instance. Then use the same context instance to do RewritePath. This will now mean that all HTTP requests to this web application will go through this code. Here's a very primitive example that captures the spirit of what we're trying to do:

	public class SomeModule: IHttpModule
	{

		public void Init(HttpApplication context)
		{
			context.BeginRequest += new EventHandler(Application_BeginRequest);
		}

		

		private void Application_BeginRequest(object sender, EventArgs e)
		{
			HttpContext httpContext = HttpContext.Current;

			string guid = httpContext.Request.Path;

			// check that the guid is just a guid and not a compete path
			string path = httpContext.Request.Path;
			bool someCondition = DoSomethingInteresting(path);
			if ( someCondition )
				httpContext.RewritePath( "Blog.aspx", httpContext.Request.PathInfo, string.Format("guid={0}", guid) );
			else
				httpContext.RewritePath( "Pictures.aspx", httpContext.Request.PathInfo, string.Format("guid={0}", guid) );
		}

		// More code and stuff below.
		...		
	}

The point of the above code snippet is to demonstrate that we can decide the target page for our web request based on the url. DoSomethingIntersting determines from the url the user passed whether to transfer control to the blog page or the Pictures page. Naturally, any real system would be considerably more complex than this but this example captures the essence of what we're trying to achieve. And really that's all there is to it. ASP.net makes everything easy :)

Simon

20:25:37 GMT | #Programming | Permalink
XML View Previous Posts