Andrew Stevenson's WebLog

Write Here Write Now

Syndication

.Net Languages

ADO.Net

Asp.Net (Misc.)

Asp.Net Controls

Bad Patterns

Err What?

Files and Folders

Forums

IE Add-Ins

Methods for the Madness

Performance

See Clearer, C#

Test Driven

Url Rewriting/Remapping with an IHttpHandlerFactory

I've tried rewriting urls a couple of times and I've settled on using an IHttpHandlerFactory. It isn't perfect, but it works.

The question came up again in a forum, so I'm posting my sample with an implementation based on the question.

There are 3 classes in the example:

  • RemapHandler (an abstract base class)
  • RemapInfo (utility class for a pair of value)
  • CultureInUrlHandler (the example implementation)

The code assumes that you will be running in an application called ForumHelpExamples. It takes a request fo localhost/ForumHelpExamples/en-ca/Default.aspx extracts the en-ca to set the thread culture and executes localhost/ForumHelpExamples/Default.aspx. The CultureInUrlHandler could easily be changed to add a querystring parameter too. 

using System.Web;
using System.Web.UI;
namespace ForumExamplesLibrary
{
    abstract public class RemapHandler : IHttpHandlerFactory
    {
        protected RemapHandler()
            : base()
        {
    
   }
        IHttpHandler IHttpHandlerFactory.GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
        {
            RemapInfo target = GetRemapInfo(context, requestType, url, pathTranslated);
            string filename = context.Server.MapPath(target.VirtualPath);
            //Rewrite path is called to update the query string values
            context.RewritePath(url, url, target.QueryString);
            IHttpHandler appHandler = PageParser.GetCompiledPageInstance(target.VirtualPath
                , filename
                , context);
            return appHandler;
        }
        void IHttpHandlerFactory.ReleaseHandler(IHttpHandler handler)
        {
        }
        protected abstract RemapInfo GetRemapInfo(HttpContext context, string requestType, string url, string pathTranslated);
    }
}

namespace ForumExamplesLibrary
{
    public class RemapInfo
    {
        private string _virtualPath;
        private string _queryString;
   
        public RemapInfo( string virtualPath, string queryString)
        {
            this._virtualPath = virtualPath;
            this._queryString = queryString;
        }
        public string VirtualPath
        {
            get { return _virtualPath; }
        }
        public string QueryString
        {
            get { return _queryString; }
        }
    }
}


using System;
using System.IO;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Globalization;
using System.Threading;

namespace ForumExamplesLibrary
{
    public class CultureInUrlHandler : RemapHandler
    {
        protected override RemapInfo GetRemapInfo(HttpContext context
            , string requestType
            , string url
            , string pathTranslated)
        {
            string originalPath = HttpContext.Current.Request.Path;
            string stemPath = "ForumHelpExamples/";
            string newPath = originalPath.Substring(originalPath.IndexOf(stemPath) + stemPath.Length);
            string[] segments = newPath.Split('/');
            string queryString = HttpContext.Current.Request.ServerVariables["QUERY_STRING"];
            try
            {
                string languagePart = segments[0];
                //It will be inefficient to throw exceptions when the lang is invalid
                CultureInfo ci = new CultureInfo(languagePart);
                System.Threading.Thread.CurrentThread.CurrentCulture = ci;
                return new RemapInfo("/" + stemPath + string.Join("/", segments, 1, segments.Length - 1)
                    , queryString);
            }
            catch (NullReferenceException)
            {
            }
            return new RemapInfo(originalPath, queryString);

        }
    }
}
 
And in the web config...
<system.web>
 <httpHandlers>
   <add verb="*" path="*.aspx" type="ForumExamplesLibrary.CultureInUrlHandler, ForumExamplesLibrary"/>
  </httpHandlers>
 
 
Edit:I was posting this in a commment, figured it would be good to add it here.
You can have query string variables and they work as normal. 
The example just looks for the language part and removes it to determinethe real page, it passes the query string along as-is
The only time you should have any issue with the qs is if you want to use it to convert parts of the path into a query string. 
Its better to keep a custom dictionary (eg "PathParamers") in the httpcontext.current items  to hold them.  (If you convert the path directly to qs arguments, so that site/color/red/All.aspx executes the pages site/All.aspx?color=red, then when you have postback, you postback to  site/color/red/All.aspx?color=red) 
 

Published Saturday, October 08, 2005 1:39 PM by AndrewSeven

Filed under: , ,

Comments

# re: Url Rewriting/Remapping with an IHttpHandlerFactory @ Friday, November 02, 2007 9:04 PM

Your a GENIUS !!!

TThanks a million

Finally a good for URL REWRITING !!!!

A+

Tief

Tief

# re: Url Rewriting/Remapping with an IHttpHandlerFactory @ Wednesday, April 23, 2008 3:38 PM

Great article, thanks for leaving a comment and showing me the factory approach

albertpascual

# re: Url Rewriting/Remapping with an IHttpHandlerFactory @ Saturday, May 02, 2009 6:24 AM

pls, give me a code sample?

I tried but not run.

pls, help me

Thanks alot

Jonathan Nguyen

# re: Url Rewriting/Remapping with an IHttpHandlerFactory @ Tuesday, May 12, 2009 1:13 PM

Jonathan : This is the code sample, it shows the IHttpHandlerFactory approach. The sample worked when I posted it.

AndrewSeven

Leave a Comment

(required) 
(required) 
(optional)
(required)