I recently had a situation where a custom control I was using in a page required jQuery. Since I like the idea of keeping such controls self-contained, I added the usual <script type="text/javascript" src="jquery-1.2.6.min.js"></script> tag.
No problem – until I then loaded a page that included this control AND also had its own requirement for jQuery. It seems that jQuery doesn’t like begin included twice, so I had a choice. I could:
- Include jQuery once in the header (or wherever) of each page (i.e. in the Master Page), hence breaking the self-containment of my control, or;
- Write a helper method to keep track of which script files had been included in each page and hence allow a script file to only be included once per request.
It should come as no surprise (as otherwise there would be no point in this post) that I went for the second option.
The HttpContext object has an Items collection, and since the HttpContext has a lifetime of one request, we can use this Items collection to keep track of our included files. Just add the following static method to a static class (Don’t you just love Extension Methods!):
public static string InsertScript(this HtmlHelper helper, string jsFile)
{
const string RESID = "__resources";
List<string> _resources = (List<string>)helper.ViewContext.HttpContext.Items[RESID];
if (_resources == null)
{
_resources = new List<string>();
helper.ViewContext.HttpContext.Items[RESID] = _resources;
}
string url = ScriptUrl(jsFile);
if (!_resources.Contains(url.ToLower()))
{
_resources.Add(url.ToLower());
return "<script type=\"text/javascript\" src=\"" + url + "\"></script>";
}
else
return "";
}
Notice the call to ScriptUrl(jsFile) – this is just a static helper method to map javascript file names to the Scripts folder in my web app. It’s up to you whether you use such a method.
It’s now just a matter of calling this from your .aspx pages, replacing the usual
<script type="text/javascript" src="myjavascriptfile.js"></script>
with
<%= Html.InsertScript("myjavascriptfile.js") %>
