What is the preferred method to reference external files from my ASP.NET web control?
My web control needs to access two external files. One is a CSS file. The other is a JavaScript file.
<link href="<%= VirtualPathUtility.ToAbsolute("~/css/mycss.css") %>" rel="stylesheet" type="text/css" />
<script src="<%= VirtualPathUtility.ToAbsolute("~/scripts/myjs.js") %>" type="text/javascript"></script>
The page could potentially contain multiple instances of my control. Of course, I only want the page to include a single reference to each file.
I looked at the Page.ClientScript properties and methods. But it doesn't appear to have one specifically for CSS.
I also looked at using something like Page.Header.Controls.Add(link), but this doesn't appear to have direct support for preventing multiple references to the same file.
Is there another option?
Okay, so apparently there is no preferred method for this:
The following seems to be working:
if (!Page.ClientScript.IsClientScriptIncludeRegistered("MyControl.ascx.cs"))
{
Page.ClientScript.RegisterClientScriptInclude("MyControl.ascx.cs", ResolveClientUrl("~/scripts/myjs.js"));
HtmlHead head = (HtmlHead)Page.Header;
HtmlLink link = new HtmlLink();
link.Attributes.Add("href", "~/css/mycss.css");
link.Attributes.Add("type", "text/css");
link.Attributes.Add("rel", "stylesheet");
head.Controls.Add(link);
}
Related
I have an ASCX user control in the root of my Web application. It references a stylesheet, something like
<link type="text/css" rel="stylesheet" href="MyStyle.css" />
The problem is if any ASPX pages located in application subfolders reference that user control - they don't see the stylesheet, because href path is relative and stylesheet remains in the app root.
Is there a way besides copying the CSS into all the subfolders to universally reference it from the root? I have no problem referencing external JavaScript, using ScriptManagerProxy I can specify path to external JS file via ASP.NET "~/" notation which gets resolved into real path from any location. Does something similar exist for CSS?
ResolveUrl will convert application-relative urls for you. http://msdn.microsoft.com/en-us/library/system.web.ui.control.resolveurl.aspx
<link href="<%= ResolveUrl("~/MyStyle.css") %>" rel="stylesheet" />
EDIT: If you don't want to use inline code blocks
code-behind
protected void Page_Load(object sender, EventArgs e)
{
litStyle.Text = string.Format("<link href=\"{0}\" rel=\"stylesheet\" />", ResolveUrl("~/MyStyle.css"))
}
markup
<asp:Literal ID="litStyle" runat="server"/>
As I mentioned in my comments I didn't want to use <%= %> blocks. But I didn't want to assign URL of CSS file in code-behind either, so I found a compromise. I declare <link> tag with runat="server" attribute and ASP.NET - style href:
<link rel="stylesheet" type="text/css" runat="server" id="xlinkCSS" href="~/MyStyle.CSS" />
and then in code-behind simple resolve that link
xlinkCSS.Attributes("href") = ResolveUrl(xlinkCSS.Attributes("href"))
Using this approach ultimately I can create a function that accepts page as a parameter, loops thru all "link" tags, resolving their URLs.
Actually you have two options:
1- to include it in your themes folder, then the asp.net framework will automatically include it in all pages using this theme
2- to add a public variable in your CS code that includes the path, then to use it in your code, as the following code:
public string basepath = "http://" + Request.Url.Authority + Request.ApplicationPath;
then to use it in ASP code:
<link type="text/css" rel="stylesheet" href="<%=basepath %>MyStyle.css" />
You should make bundle.config file and then you can use this in your code
I am implementing a web application using ASP.NET MVC3. In the application I want to add the option of switching between CSS files (for themes) based on clicking some links. I did some research and I came up with the following:
To pass data to site.master, the good solution is to create an abstract controller and inherit that into the other controllers that have site.master as their template, according to this article: Passing Data to View Master Pages
I can pass a viewbag message to the link which controls the css file URL to set the current css file to use, based on the code that I am seeing being passed to scripts at the top of the site.master page:
script src="<%: Url.Content("~/Scripts/jquery-1.5.1.min.js") %>" type="text/javascript"
So I created an abstract controller, ApplicationController, with the following method:
public ApplicationController()
{ViewBag.NewMessage = "../../Content/Site2.css";}
And in the site.master, I included this link:
<link href="<%: (string) ViewBag.NewMessage %>" rel="stylesheet" type="text/css" />
However, that doesn't seem to be working, as it is being interpreted as:
<link href="<%: (string) ViewBag.NewMessage %>" rel="stylesheet" type="text/css" />
And only when I remove the quotation marks:
<link href=<%: (string) ViewBag.NewMessage %> rel="stylesheet" type="text/css" />
is it being interpreted correctly (and the webpage gets rendered with the correct css), except that it violates html standards:
<link href=../../Content/Site2.css rel="stylesheet" type="text/css" />
Any suggestion about how to go tackling this problem or is there a more elegant solution I'm missing? I was going to proceed and implement variables in the ApplicationController that get selected based on links the user clicks at the top of the page, to switch between css styles.
Thank you!
Check to make sure your <head> tag does not have runat="server".
After making this change, be sure to check your script and css tags. This change can break the paths if you use the ~/ to ref app root. To help with this, use the Url.Content(...) helper.
I have a situation where I need to dynamically load a URL prefix.
I wrote a quick control to handle this and it works for the following instance:
<script type="text/javascript" src='<gbn:AdminPath runat="server" id="Id1" />Rest/Of/Path.js'></script>
But the following case (on the same aspx page) does not work:
<link rel="stylesheet" href='<gbn:AdminPath runat="server" id="Id2" />/css/styles.css'>
This shows up in the browser as:
<link rel="stylesheet" href="<gbn:AdminPath runat="server" id="Id2" />/css/styles.css" />
I've tried various things, but I can't seem to get the tags working. Any suggestions?
Thanks
The problem here is that it treats <link> elements in the <head> section like they are server controls. It does this, I believe, so that you can use app-relative urls (eg "~/myfolder/file.css") and have them resolved for you. It does not give this same treatment to <script> tags, though.
Since they are treated as server controls, you cannot mix inline script and string literals in a property value or it all gets treated as a literal (as you discovered).
To get around this, you have several options, one of which TheGeekYouNeed outline above.
If you still want to do it inline with a public method, you can, but you have to build the whole property value in your code like the following:
<link rel="stylesheet" href='<%= string.Format("{0}/css/styles.css", GetAdminPath() %>' type="text/css" />
Add the in the code behind
example:
// Define an HtmlLink control.
HtmlLink myHtmlLink = new HtmlLink();
myHtmlLink.Href = GetAdminPath() + "/pathtocss.css";
myHtmlLink.Attributes.Add("rel", "stylesheet");
myHtmlLink.Attributes.Add("type", "text/css");
// Add the HtmlLink to the Head section of the page.
Page.Header.Controls.Add(myHtmlLink);
I have a server control that needs to programmatically inject a JavaScript reference into the page. It is to reference Microsoft's Bing map control which requires &s=1 to be appended to the script URL for use over SSL. The problem is that the .NET Framework encodes the attributes and changes the & to an & (verified with Reflector). At some point after that the & is removed altogether.
Desired script tag:
<script type="text/javascript"
src="https://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2&s=1">
</script>
Attempt 1:
var clientScriptManager = this.Page.ClientScript;
if (!clientScriptManager.IsClientScriptIncludeRegistered(this.GetType(), "BingMapControl"))
{
clientScriptManager.RegisterClientScriptInclude(
this.GetType(), "BingMapControl",
"https://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2&s=1");
}
Attempt 2:
HtmlGenericControl include = new HtmlGenericControl("script");
include.Attributes.Add("type", "text/javascript");
include.Attributes.Add("src",
"https://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2&s=1");
this.Page.Header.Controls.Add(include);
Any ideas?
Desired script tag:
<script type="text/javascript"
src="https://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2&s=1">
</script>
Actually, no. In fact, your desired script tag is:
<script type="text/javascript"
src="https://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2&s=1">
</script>
You do want the & to be encoded as &. Why? Because the HTML standard says so. See, for example, Section C.12. Using Ampersands in Attribute Values (and Elsewhere) of the XHTML 1.0 standard:
In order to ensure that documents are compatible with historical HTML user agents and XML-based user agents, ampersands used in a document that are to be treated as literal characters must be expressed themselves as an entity reference (e.g. "&"). For example, when the href attribute of the a element refers to a CGI script that takes parameters, it must be expressed as http://my.site.dom/cgi-bin/myscript.pl?class=guest&name=user rather than as http://my.site.dom/cgi-bin/myscript.pl?class=guest&name=user.
Out of curiosity... is this code just an example? I generally only use RegisterClientScript and its ilk if there is some dynamic portion that needs to be set at runtime. Otherwise, you can just write it statically in an aspx, ascx, or js file.
Have you tried a Literal control? I know I've done this very thing recently. I'll have to dig up my code.
It seems like all controls added to Header are html.encode-d
Page.Header.Controls.Add
Quick solution is to add a property ScriptUrl
public string ScriptUrl
{
get
{
return "https://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2&s=1";
}
}
and in aspx
<head runat="server">
<title></title>
<script type="text/javascript" src="<%= ScriptUrl %>"></script>
</head>
And that's all
Hello all I have a problem. I have a masterpage that all of my Content pages inherit from. Within this masterpage I have a script tag pointing to the Javascript file folder ~/Scripts/validation.js
On my content pages I use different usercontrols that require the use of many of the functions within the validation.js file however if I dont put the <script> tag and the Javascript functions within a contentholder on the contentpage the usercontrols do not see these functions and I get errors like OnNameValidation is not defined.
Of course I can copy the Javascript code into all of the pages but that's 30+ pages and a maintenance nightmare if I find a bug in one of the Javascript functions.
So the question (if you haven't already figured out from my long dissertation) is how can I declare the script tag with the path to the validation.js file so that contentpages and their usercontrols etc. can access the functions/code.
What you are trying to do should work, so I suspect that the path to your javascript file is wrong (without seeing your html code I can only assume). Keep in mind that you can only reference the javascript file like this: "~/Scripts/validation.js" if you have the link in a HEAD runat="server" tag. Without the runat="server" it won't find the file. You would have to do something like "../scripts/validation.js"
As a test I would try to call your javascript function in the masterpage, so you can rule out a bad file reference.
I picked up this tip from ScottGu here.
Add this to you user control which enables Intellisense in user controls but always evaluates false:
<% if (false) { %>
<script src="/Scripts/validation.js" type="text/javascript"></script>
<% } %>
I am currently doing this in my site by going to the Source code on the master page and putting the following in the head and outside of the ContentPlaceHolder.
<head>
<asp:ContentPlaceHolder ID="HeadContent" runat="server">
</asp:ContentPlaceHolder>
<script src="CP.js" type="text/javascript"></script>
</head>
The path you are assigning for your js file is probably not matching in all the pages.
script src="../JavaScript/Scriptaculous/scriptaculous.js"
It should have something like above this if you have separate folder for Scripts, MasterPages, Pages & Controls.