Relative links to scripts when using ASP.NET Routing

Recently, I have ported our web site management solution to take advantage of System.Web.Routing to create clean urls for customer content. In short it is a content management system (plus some other bits and pieces).

Taking a simple example, I was configuring a customer site (i.e. taking the raw design from the web designer and plugging in the bits and pieces to make it dynamic). Let’s say this site has two views (or aspx pages). We are not using MVC yet, but be are using the concept, so this site had a content.aspx page and a jobs.aspx page. I use ASP.NET Routing to avoid having links to /content.aspx?pageID=3 – and instead having something like /services/how_we_do_things (under the hood its still rendering content.aspx and loading page 3 into it – I’m sure you can work out conceptually how that’s working). I set up my routing in the global.asax file and everything was working fine.

The problem came when I moved onto the jobs.aspx. I had a route set to detect two routes. Either:

"vacancies" or "vacancies/{id}"

… the idea being that a visit to /vacancies would just show the list of vacancies or a link to /vacancies/job-1 would find that job in the list and focus on it.

The vacancies page used some simple jQuery manipulation to do a "show/hide detail" type scenario and when visiting /vacancies that’s worked fine. But when visiting /vacancies/job-1 the link to the jquery script (the actual jQuery 1.2.6 file) was broken.

After some thinking I eventually realised that the virtual Url I was visiting meant that the physical jQuery file could not be found (in other words from /vacancies/job-1 the src attribute of the include script would have to be ../jQuery.1.2.6 etc etc.

So I decided to use a ScriptManager as this does all the dirty work of mapping the actual script locations. So I added this just inside the form tag on my aspx page.

<asp:ScriptManager ID="ScriptManager1" runat="server" LoadScriptsBeforeUI="true">
<asp:ScriptReference Path="~/jquery-1.2.6.pack.js" />
<asp:ScriptReference Path="~/vacancies.js" />

Note that as these scripts include event code (hooking up click events in the DOM) I have included the parameter LoadScriptsBeforeUI="true" (its basically an equivalent of having the script in the <head> section. As the Script Reference Path property includes the ~ character at the start of the path, the mapping is automatically done to alter the path regardless of the virtual url I navigate to.

Next problem, Routing was interfering with ASP.NET AJAX (in short trying to process calls to .axd files (common to ASP.NET AJAX scenarios). The solution was to include a routing rule to stop Routing processing those files. Below is Application_Start and registering methods from my global.asax file for reference:

void Application_Start(object sender, EventArgs e) 

public static void RegisterRoutes(System.Web.Routing.RouteCollection routes)
    System.Web.Routing.Route r = null;

    r = new System.Web.Routing.Route("{resource}.axd/{*pathinfo}", new System.Web.Routing.StopRoutingHandler());

    r = new System.Web.Routing.Route("vacancies/{id}", new VacanciesHandler());

    r = new System.Web.Routing.Route("{page}", new wf24RouteHandler());

    r = new System.Web.Routing.Route("{page}/{sub1}", new wf24RouteHandler());

All fixed and working perfectly. I can’t wait to get my hands on the RTM MVC bits.

This post is a rush job as I wanted to document what I did for own benefit as well as others. If there is anything you need clarification on or if you have any other questions, please leave a comment. Trust me, I’ve probably already been there :)


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s