This post is about the different way to write paths in User Control, and about the special ASP.NET Web Application root operator.
Ever wondered how paths in ASP.NET User Control are resolved when the control is being consumed by web pages in different locations? I did. So I made a simple control named
MyControl.ascx in a folder called
/UserControls. The UserControl displays an image called
MyImage.jpg which is located in a folder called
The challenge is that I want to use my control from different pages, located in different folders in my Web Application. (As an example here, I am using a page located in the root of the application and another page located in a folder called
/Pages). So how should I refer to the image from my control?
One way to do this is by using a site-root relative path:
<img src="/UserControls/Images/MyImage.jpg" alt="">
This will work on both pages, but the obvious disadvantage of this approach is that the Web Application then needs to run in the webroot (or some other known path). And if I reuse my control in some other project, I need to keep the locations or change my mark-up. I could probably use the HTML base element to avoid some of these disadvantages though.
The second way to do it is by a “truly” relative path. Here I actually got two option: By using a ordinary (client side) HTML tag, the path will be embedded in the page as it is, and the relative path in my mark-up must be relative to the consuming page:
<img src="UserControls/Images/MyImage.jpg" alt="">
This is generally not a useful behavior, because all consuming pages must be placed in the same location. In this case, the page located in
/Pages will not display the image.
As an alternative, I can render the img as a HTML server control. By doing this I tell ASP.NET to process the img tag (including the path) before sending it to the client. This will change a path relative to my control to a path relative to the consuming page. Hence
<img src="Images/MyImage.jpg" runat="server" alt="">
will be rendered as
in the HTML sent to the client. Notice that ASP.NET removes a empty alt attribute – not good. Otherwise this behavior it more what I am looking for: The relative path will be adapted as the control is consumed on different locations.
The third way is by using the Web Application root operator
~/. This operator will resolve to the Web Applications root, even is the application is running in some subfolder. The rendered HTML will include a relative path, resolved by ASP.NET. This means that the img tag must be rendered as a HTML control:
<img src="~/UserControls/Images/MyImage.jpg" runat="server" alt="">
will render as
<img src="UserControls/Images/MyImage.jpg" runat="server" alt="">
The disadvantage here is that I need to know the location of the resource relative to the Web Applications root, and change my mark-up if this location changes. This can happen here because the resource is tied to my control, and it may want to copy the control and its resources to another project/location.
All of these three (actually four) approaches will work, and to decide which one to use in your project, you may want to ask these questions: Will the control be used in other projects? Will the location of the application change, e.g. from the testing and staging environment to the production server? Will the locations of the resources (images) change. Is the resources logically tied to the control or tied to the current application?
2 responses to “Paths in User Controls”
When using a HTML server control setting the AppRelativeTemplateSourceDirectory property can resolve the path to a directory outside the user controls path.
Awesome! runat=”server” really does something here