For projects where individual controls/sublayouts control the scripts that they include on the page, I typically use Page.ClientScript to manage script inclusions.
ClientScriptManager has a number of useful methods for including scripts within a page, and will detect if a script has already been included by comparing the types and script names so that scripts aren't included multiple times (could be nice for handling dependencies, but I prefer to use requirejs).
The three main script registration methods are:
RegisterClientScriptBlock
RegisterClientScriptInclude
RegisterStartupScript
RegisterClientScriptBlock dumps the script at the top of the page
Page.ClientScript
.RegisterClientScriptBlock(
GetType(),
scriptName,
"<script>alert('do stuff');</script>");
RegisterClientScriptInclude dumps <script src=""> at the top of the page
Page.ClientScript
.RegisterClientScriptInclude(
GetType(),
scriptName,
"path/to/scriptname.js");
RegisterStartupScript dumps the script at the bottom of the page
Page.ClientScript
.RegisterStartupScript(
GetType(),
scriptName,
"<script>alert('do stuff');</script>");
Unfortunately there's no native RegisterStartupScriptInclude which would allow for external scripts to be added to the bottom of the page, so I wrote an extension method:
public static class ClientScriptManagerExtensions
{
/// <summary>
/// Registers the startup script with the <see cref="Page"/> object using a type,
/// a key, and a url
/// </summary>
/// <param name="source">
/// The <see cref="ClientScriptManager"/> with which the script should be registered
/// </param>
/// <param name="type">The type of startup script to register</param>
/// <param name="key">The key of the startup script to register</param>
/// <param name="url">The url of the startup script include to register</param>
public static void RegisterStartupScriptInclude(this ClientScriptManager source,
Type type,
string key,
string url)
{
if (source == null)
throw new ArgumentNullException("source");
var script = string.Format(@"<script src=""{0}""></script>", HttpUtility.HtmlEncode(url));
source.RegisterStartupScript(type, key, script);
}
}
This allows developers to register external scripts to be executed at the close of the </form> element, which tends to be close enough to </body> for purposes of performance.
Page.ClientScript.RegisterStartupScriptInclude(Page.GetType(), "jquery", "path/to/jquery.js");
Page.ClientScript.RegisterStartupScriptInclude(GetType(), "mycontrol", "path/to/mycontrol.js");