Sunday, September 26, 2010

Automatic URL re-basing in the HtmlHead control

If you're using Master Pages in ASP.NET and trying to resolve <script> or <style> references in the page head, you may have run into this this show-stopper. If so, here's why it's happening, and here's an easy way to fix it.

If you've worked with ASP.NET Master Pages, you've no doubt taken advantage of automatic URL re-basing within the HtmlHead control. This bit of ASP.NET magic helps assure that a content page has access to the correct resources:

<head id="head1" runat="server">
<title>My Page</title>
<link href="css/common.css" rel="stylesheet" type="text/css" />
</head >

When you add the runat="server" attribute to the tag,
 the runtime treats it as an HtmlHead control. The HtmlHead control has the ability to parse child <link> controls contained withing it, so that when a content page is rendered, the URL in the href attribute points to the correct file.

The Problem

Now, let's say you also want to place a reference to an external JavaScript file in the <head>, so you do this:

<head id="head1" runat="server">
<title>My Page</title>
<link href="css/common.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="javascript/leesUtils.js"></script>
</head>

Naturally, you might assume that URL re-basing will help you out here, but you'd be mistaken. Unfortunately, the runtime doesn't automatically re-base URLs in <script> or <style> tags, so any page not in the same directory as your master page won't find your script or CSS files.

The Solution

So, if HtmlHead won't resolve your URL automatically, you'll wrestle that sucker manually by using the Control.ResolveUrl method.
ResolveUrl can take a URL that is relative to the root of the application and correct it for the current request path.

You'd then use a code block to substitute the correct URL at runtime:
<head id="head1" runat="server">
<title>My Page</title>
<link href="css/common.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="<%# ResolveUrl("~/javascript/leesUtils.js") %>"</script>
</head >

3 comments:

Anonymous said...

Its cool!! I like your blog very much.
Please keep it up

Unknown said...

Thanks......

Anonymous said...

URL re-basing is not necessary. If the pages are at same level but different directories, then relative paths can be used, for e.g. going 2 directories up, then scripts folder, then the actual script file.

"../../Scripts/myScripts.js"

Method 'StartWorkflowOnListItem' in type 'Microsoft.SharePoint.WorkflowServices.FabricWorkflowInstanceProvider'

Exception: Method 'StartWorkflowOnListItem' in type 'Microsoft.SharePoint.WorkflowServices.FabricWorkflowInstanceProvider'...