.NET base href & stylesheet links in subfolder

6.3k Views Asked by At

I thought I'd use the base href tag to make my relative URLs work on different installations.

In my master page, I have:

<base href="http://localhost/myproject/" />
<link rel="stylesheet" type="text/css" runat="server" href="css/main.css" />
<script type="text/javascript" src="js/jquery.min.js"></script>

That works fine when I'm on http://localhost/myproject/default.aspx, the css path resolves fine, such as: http://localhost/myproject/css/main.css

But then I have a subfolder, reports. When I navigate to http://localhost/myproject/reports/default.aspx, and view source, this is what I see:

<base href="http://localhost/myproject/" />
<link rel="stylesheet" type="text/css" href="../css/main.css" />
<script type="text/javascript" src="js/jquery.min.js"></script>

Something has injected the ../ into the href attribute of the link tag, which means it's resolving as: http://localhost/css/main.css which is not found.

This is odd, because it's working as I'd expect for the script tag; just the link tag gets this injection. I viewed source in IE & Chrome and both were the same, so I assume it's IIS/.NET that's doing it, but they shouldn't really touch the HTML because it's not runat="server". Playing with this a little, I see the link tags on the Master page are modified, but not the script tags (if they're relative URLs without the leading "/"). I assume that's because they're "src" attributes and not "href" attributes. So having / not having the base href will fix the one type but break the other.

Am I going crazy, is this a bug, or am I holding it wrong?

EDIT: I'm not actually hard-coding the href of the base tag. I'm writing out the value of a setting that is loaded to application memory from a database table. So it's actually doing: <base href="<%=Settings.Configuration.website_rooturl%>" /> where on my dev machine the value could be http://localhost/ or http://localhost/project/ and on one client site it's http://www.clientsite.com/ and another client site it's a virtual directory http://www.clientsite2.com/project/.

5

There are 5 best solutions below

5
On

Try using ~, as in <link rel="stylesheet" type="text/css" href="~/css/main.css" />

In ASP.NET applications, the ~ refers to the root directory of the app.

11
On

Resolve it from the root using the '~' (tilda) operator. You also need to add the runat="Server" attribute for this to work:

<link rel="stylesheet" type="text/css" runat="server" 
    href="~/css/main.css" runat="server" />

You don't need a base tag value from a DB for your site to work on different installations. Lose it completely. You also have the ability to configure virtual directories any way you want on different servers.

1
On

The issue is apparently this. Because I have a head tag with runat="server", the link stylesheet & favicon tags are being treated as HtmlLink controls, so the href attribute gets rendered differently (injected with the ../).

This seems to fix it, as the empty double quotes in the inline code forces it to be outputted as an HTML control, rather than an HtmlLink ASP.NET web control:

<base href="http://localhost/myproject/" />
<link rel="stylesheet" type="text/css" runat="server" href="<%=""%>css/main.css" />
<script type="text/javascript" src="js/jquery.min.js"></script>

Strange, but true.

0
On

I realize that this is by now a very old question, but I ran into the same issue today (five years after the initial post), and I was able to solve it like this.

<%="<base href='" + Page.ResolveUrl("~/") + "'/>" %>
<!-- or however you want to get the base -->

Apparently, ASP.NET interprets the base tag when it's found in a page, and does things to other server-side tags. So, I just made it so that the engine didn't see it as a control. It's a hack, but it worked.

In addition to the OP's <link> tags, <asp:ImageButton> tags were similarly affected. This hack fixed both.

1
On
<link href="<%= ResolveClientUrl("~/css/main.css") %>" rel="stylesheet" type="text/css" />