2

Rewriting Question

I cannot, for the life of me, get relative image paths work consistently inside usercontrols between using VS's dev server and publishing to a remote IIS server. I do not want to make my image a server tag by adding runat="server". I want it to be strictly client and I do not want to use any hocus pocus code hacks. I want to resolve the disconnect, so here is my problem:

My images are stored in ~/images. My usercontrols are stored in ~/usercontrols/anothersubfolder.

When I do this...

<img id="myimage" src="../../Images/help.png" alt="" />

...the image loads when using the VS dev server (localhost), but not when I deploy to a remote IIS virtual directory. However, when I do this...

<img id="myimage" src="<%=Request.ApplicationPath %>/Images/help.png" alt="" />

...it works when I publish remotely, but not using the dev server!

I need a solution that works for both the VS dev server AND when I publish remotely. As I said, I do not want to add runat="server" to my image tag or use any code hacks. There is a disconnect here and I want to know how to go about resolving that.

oscilatingcretin
  • 10,457
  • 39
  • 119
  • 206

7 Answers7

5

Try it like this:

<img src="~/Images/indicator.gif" border="0" alt="" runat="server" />

Avoiding problems with relative and absolute URLs in ASP.NET

Control.ResolveUrl versus Control.ResolveClientUrl versus VirtualPathUtility.ToAbsolute

ResolveUrl vs. ResolveClientUrl

Community
  • 1
  • 1
IrishChieftain
  • 15,108
  • 7
  • 50
  • 91
  • As stated in my question, I already know that a server-side control will generate a proper relative path (see how I used an ASP Image control). It's just that I don't want to use a server control for this. – oscilatingcretin Aug 08 '12 at 14:47
  • You don't need to use a server control. By adding the runat attribute, the HTML control will resolve correctly on the server side. – IrishChieftain Aug 08 '12 at 14:49
  • But doesn't it take up space in the ViewState if it has `runat="server"`? – oscilatingcretin Aug 08 '12 at 14:54
  • No, the image will be cached by the browser. ViewState would be minimal, if any. – IrishChieftain Aug 08 '12 at 14:55
  • @IrishChieftain: but without runat="server" it's not working!? – Nikolaj Zander Aug 08 '12 at 14:56
  • That's correct behavior. By resolving on the server side, it will search downwards from the root and locate the image. – IrishChieftain Aug 08 '12 at 14:57
  • This answer sort of circumvents the essence of the question, which is why his client side path does not work when it is placed on a page. He did not ask for a solution involving a server path. Good link for reference though. – pseudocoder Aug 08 '12 at 15:59
  • @pseucoder, good point. This is just the way ASP.NET works and he may need to look at ResolveUrl. Am updating answer... – IrishChieftain Aug 08 '12 at 16:15
1

It seems like you've found your own answer: The location of the ascx control doesn't change relative paths. The aspx page loading the ascx control ultimately determines the paths (this will extend to your CSS and JS files, if you're using any).

I "solved" this problem by never using relative paths. My src attributes always look like <img src="/<appfolder>/Images/<filename>.<extension> />.

It's worth noting that I change my website properties and select Use Local IIS Web Server under the Web tab of the properties page. Since I don't use the Visual Studio Development Server, your mileage may vary depending on your project's configuration.

jwheron
  • 2,553
  • 2
  • 30
  • 40
  • Wow... so far, this works for publishing to the server and debugging locally using VS 2010's dev server. At first, I thought preceeding the path with a `/` just meant to go to the parent folder, but that's `../`. I am marking yours as the answer now and will award the bounty in a few after I give this some more testing. – oscilatingcretin Aug 16 '13 at 12:02
  • I had to unmark because this isn't working after all. Asking mods to extend bounty for a week because I am going on vacation and won't have time to test this until the week after next. – oscilatingcretin Aug 16 '13 at 19:44
  • The reason why this doesn't work is because, if my site is at `www.mycompany.com/mywebapp`, I have to append `/mywebapp` to the URL because `/` resolves to `www.mycompany.com`. This is a problem if there are multiple versions of the site in different virtual directories (`/mywebappdev` vs `/mywebappbusinesstesting` for example). – oscilatingcretin Aug 26 '13 at 13:58
  • I get what you're saying, but having multiple versions of the same site on the same server is a **really** bad practice. Do not ever do this under any circumstances. If you don't have a testing server, set this up on your development machine. Do not ever deploy test versions of websites to production. – jwheron Aug 26 '13 at 20:40
  • Secondly, if you're truly testing your website, your resources can change as well (different image sizes, logo redesigns, screenshot updates, etc.), and your code would have to change to accommodate that. You should always deploy your resources to be consistent with the directory in which it resides (or set up a CDN) to avoid permissions issues. – jwheron Aug 26 '13 at 20:43
  • You misunderstood. On a single domain, there are several versions of the same site deployed to different virtual directories. We have a dev site (/mywebappdev) where the business can test changes for the current release. We then have a certification site (/mywebappcert) which is a copy of production, but pointing to a dev database. I don't know where you derived that I was deploying dev code to production. – oscilatingcretin Aug 26 '13 at 21:30
  • No, I get you. I'm saying that I think this is a bad practice, and that you should have separate servers for dev/test code. – jwheron Aug 26 '13 at 21:44
  • I do not see a problem with having multiple dev sites hosted by IIS on the same box. If it's actually bad practice, I can only assume you are going to provide an objective explanation as to the measurable consequences of doing this. – oscilatingcretin Aug 26 '13 at 21:50
  • I'll look up sources for this after work, but briefly: let's just assume that you (or another developer) accidentally introduces a bad bug into either test or dev code that gets pushed up to the same server as your production website. Now your production website's availability is vulnerable (to whatever you imagine). Sure, you can take steps to limit the vulnerability through IIS settings, but you aren't eliminating the vulnerability. – jwheron Aug 26 '13 at 22:00
  • The production website *is* on another server (I don't know why we're talking about the production server). Regardless, someone could still publish dev code to the production box if they're not paying attention to the path in the publish settings dialog. – oscilatingcretin Aug 26 '13 at 22:26
  • Urgh, okay. I'm starting over here, because there's clearly a miscommunication between our terminology usage. The point of my answer was to agree with your question, and state that you can specify an absolute path to your application. If your absolute path changes, then you have to change your config. It isn't automatic, and I never indicated that it was. If you change the URL, and your absolute path breaks, that isn't the fault of my answer. – jwheron Aug 26 '13 at 22:42
1

As others already answered, a user control ".ascx" is being loaded by the page that contain it and btw it is the same thing with master pages - they are being loaded by the page. So any relative path you describe in your script is relative to the location of the page.

So putting <img id="myimage" src="~/Images/help.png" alt="" runat="server" /> or simply use the server side control for image, will solve your problem technically..

But from what I understand your problem is less technical as you probably knew that..
So left to assume is that your problem is more conceptual regarding the morphing of a simple html control into what you describe as 'code-hack'.

You must acquire yourself with the "standards" regarding working with asp.net,
and to do that you first need to understand that asp.net is a system that aims to generate a page on server side and afterwards deliver this newly created dynamically generated page to the client side - this is the main benefit of working with asp.net and is the highest principal of it!!
This is why your page in asp.net is not .html - it is .aspx even though the script generated later will only be html.

So if you agree with my previous paragraph you also understand that any .aspx page you create is being processed by your server before delivery and the script tags you put in it are just a set of instruction regarding of how to process it dynamically. adding runat="server" only means that the attributes and content of a script tag requires server side special attention during the generation process of the resulting html page.

The aspx page you have in VS and the aspx page generated for your browser are not the same entity.
runat="server" never appears to the script being delivered to your client side.

Writing script in asp.net is not writing html - it is writing meta instructions that aim to influence what the generated html would contain.

I hope that by now I convinced you to use the provided best technical solution as a normal and natural standard in asp.net with no grief or regrets.

G.Y
  • 6,042
  • 2
  • 37
  • 54
1
<img id="myimage" src='<%= ResolveUrl("~/src/....") %>'/>
YManaf
  • 61
  • 3
0

when you run it locally you are using your folder you created and you are working in, after publish your control maybe ended up in a controls folder created by VS and your original filestructure with 2 folders is gone. Check the filesystem after publish and reorder your work-folders.

Nikolaj Zander
  • 1,270
  • 9
  • 13
  • The folder structure is identical. As I noted in the update to my question, I think it's trying to use the path relative to the page it's rendering in instead of the actual location of the control. – oscilatingcretin Aug 08 '12 at 14:49
  • i checked out all my old controls and i have to admit i always used server-controls! Guess you have to stick with ! – Nikolaj Zander Aug 08 '12 at 14:54
0

Relative paths in user controls are relative to the page they appear on, not the location of the user control. This is basically what you are stating in your update, I believe.

You should post your update as answer and accept it, or accept my answer, whichever is your preference :)

pseudocoder
  • 4,314
  • 2
  • 25
  • 40
0

Just as another possibility, ASP Parent paths are disabled on IIS by default, could this be the cause of your issue?

This article talks about how to resolve the issue if it is this. Basically, you can resolve it in a couple of ways, but the easiest is to go into the ASP settings on the IIS site and re-enable parent paths.

Obsidian Phoenix
  • 4,083
  • 1
  • 22
  • 60