60

I have an ASP.NET Razor website that is working properly when I test locally (via WebMatrix IIS).

When I put it "online" on my server, the website is not at the root of the site itself. For example:

http://intranet.mycompany.com/inform

That's basically the "root" of my folder structure, so all my folders starts from there (CSS files, default.cshtml... and so on)

My "_PageStart.cshtml" sees it properly, because when I access my site from the link http://intranet.mycompany.com/inform, it gives me the Layout I have configured in _PageStart.cshtml (and it really shows the layout + the rendered default.cshtml).

BUT nothing else is getting the proper path, for example:

<img src="~/images/logos/hdr.png" />

The img holder is there I can see it, but it shows that the link is broken. When I right-click the img holder and select properties to see where the files should be, it shows me:

http://intranet.mycompany.com/images/logos/hdr.png

So it's going to the "full" root, not the site relative root, which would be:

http://intranet.mycompany.com/inform/images/logos/hdr.png

How can I fix that?

TylerH
  • 20,799
  • 66
  • 75
  • 101
pSyToR
  • 873
  • 2
  • 7
  • 15
  • By the way at the beginning I was doing it with "/img/logos/hdr.png" and it was giving the same results – pSyToR Dec 20 '11 at 10:48
  • Ok while I was doing so more testing... I realized (and correct me if I'm wrong)... The "HTML" tags (even if it's inside an CSHTML page) are still working like normal "html" without a brain... you have to tell them everything... So my link in my webpage would need to have the /inform so it working properly? Would there be a way to make it relative ? – pSyToR Dec 20 '11 at 10:50
  • Yes, pure html in your views is rendered "as is". Just C#/VB code is rendering dynamic content. – Jan Dec 20 '11 at 11:04

3 Answers3

120

You have to use relative paths all over your app:

~ won't work within static HTML code.

You can write

<img src="@Url.Content("~/images/logos/hdr.png")" />

or

<img src="../images/logos/hdr.png" />

The first approach is good for layout files where your relative path might be changing when you have different length routing URLs.

Regarding to your question about normal links, when linking to another page in your app you don't specify the view file as the target but the action which renders a view as the result. For that you use the HtmlHelper ActionLink:

@Html.ActionLink("Linktext", "YourController", "YourAction")

That generates the right URL for you automatically:

<a href="YourController/YourAction">Linktext</a>

If you are not using MVC, you have to generate your links yourself. You have to use relative paths, too. Don't start any link with the / character!

<a href="linkOnSameLevel.cshtml">Link</a>
<a href="../linkOnParentLevel.cshtml">Link</a>
<a href="subFolder/linkOnOneLevelDown.cshtml">Link</a>

When using Layout pages you can use the Href extension method to generate a relative URL:

<link href="@Href("~/style.css")" ...
TylerH
  • 20,799
  • 66
  • 75
  • 101
Jan
  • 15,802
  • 5
  • 35
  • 59
  • Ok that could fix it with images but what about links ? – pSyToR Dec 20 '11 at 10:58
  • You don't link to a view file in mvc. You link to actions. And that is normally done with the `@Html.ActionLink()` helper. – Jan Dec 20 '11 at 11:01
  • Hi Jan... This is only a website not an application... Unless I'm not doing something properly... When I use : It gives me : CS0103: The name 'Url' does not exist in the current context... Even Visual Web Developer Express give me the same error... – pSyToR Dec 20 '11 at 12:36
  • Ah ok, you don't use MVC, right? Ok, then you don't have the html helpers available and you have to write the links yourself with relative paths. I have updated my answer. – Jan Dec 20 '11 at 12:45
  • Thanks a lot for your help Jan...Basically work as a normal webpage that's not complicated... Now my problem is that the pages are rendered cause I kinda use half MVC-half not... (It's the new CSHTML webpages) the StyleSheet doesn't move so works from the root... But once I render that is in a folder... The CSS style doesn't load properly... should I copy that css style sheet in each folder or you would see an other solution? – pSyToR Dec 20 '11 at 12:58
  • What do you mean with *I kinda use half MVC-half not*? Do you link your css from every page or from some kind of masterpage/layout page? When linking from every page, you just use relative links like ` – Jan Dec 20 '11 at 13:13
  • http://www.microsoft.com/web/post/web-development-101-part-4-using-layout Check this out you might understand better what I'm exactly using... Half MVC cause I use some "commands" inside my cshtml webpage (@RenderBody for example) that loads a web page inside the "main layout" page – pSyToR Dec 20 '11 at 13:22
  • Thanks, and additional useful point is when you want to use relative path from inside the yourself helpers. You can use this: UrlHelper urlHelper = ((Controller)htmlHelper.ViewContext.Controller).Url; and then yourImageTagBuilder.Attributes.Add("src", urlHelper.Content("~/images/yourImage.png")); hope this help. – QMaster Mar 12 '14 at 17:45
  • "Don't start any link with the / character!" Well, then you can't root your links, can you? See https://stackoverflow.com/questions/7613274/why-would-a-developer-place-a-forward-slash-at-the-start-of-each-relative-path – TylerH Jul 07 '23 at 21:17
5

Use Url.Content as shown bellow:

<img src="@Url.Content("~/images/logos/hdr.png")" />
Nikolay Kostov
  • 16,433
  • 23
  • 85
  • 123
robasta
  • 4,621
  • 5
  • 35
  • 53
0

I know that '~' is added by default, but I tend to change it so that all paths are relative to my code file rather than application root, using ".." eg. "../images/logos" etc

ChrisBD
  • 9,104
  • 3
  • 22
  • 35
  • Your code file /Things/Index.cshtml can be served either as /app/Things or /app/Things/ (with trailing slash). Plus two other ways, without the leading /app/ if you deploy to root on some server. In case of optional trailing slash the .. links will be broken. Best to enforce with server-side ~ (@Url.Content("~/....") or @Href("~/....") – Ekus May 29 '19 at 19:16