ScriptLink not accepting a query string :-(

 

A typical practice for performance is to add a revision tag (e.g., “file.js?rev=123”) to .js files so a new build, hence a new revision, brings the file to the browser cache.

Tried doing that with ScriptLink’s? No way.

Issue is, due to the processing ScriptLink goes through, we cannot add revision to those files. Say a resulting line is

                <SharePoint:ScriptLink language="javascript" name="core.js?rev=634580691801235029" OnDemand="true" runat="server" />

it gonna fail here (from Reflector)

internal static string ComputeFileHash(string filePath)
{
    FileStream stream = null;
    string str = null;
    try
    {
        new FileIOPermission(FileIOPermissionAccess.Read, filePath).Assert(); <<<<<<<<<<<<<<<<<
        using (SecurityContext.RevertToSelf())
        {
            try
            {
                stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                str = ComputeStreamHash(stream);
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
            }
            return str;
        }
    }
    catch
    {
        throw;
    }
    return str;
}

with a stack like this:

System.ArgumentException: Illegal characters in path.  
System.Security.Permissions.FileIOPermission.HasIllegalCharacters(String[] str)   
System.Security.Permissions.FileIOPermission.AddPathList(FileIOPermissionAccess access, AccessControlActions control, String[] pathListOrig, Boolean checkForDuplicates, Boolean needFullPath, Boolean copyPathList)   
System.Security.Permissions.FileIOPermission..ctor(FileIOPermissionAccess access, String path)   
Microsoft.SharePoint.Utilities.SPUtility.ComputeFileHash(String filePath)   
Microsoft.SharePoint.Utilities.SPUtility.ComputeFileHashForLocalizedLayoutsUrl(Int32 lcidUI, String name, Boolean& fUseThreadCulture)   
Microsoft.SharePoint.Utilities.SPUtility.MakeBrowserCacheSafeLayoutsUrl(String name, Boolean localizable)   
Microsoft.SharePoint.WebControls.ScriptLink.ScriptLinkInfo.ToScriptUrl(Page page)   
Microsoft.SharePoint.WebControls.ScriptLink.ScriptLinkInfo.ToScriptBlock(Page page)   
Microsoft.SharePoint.WebControls.ScriptLink.RenderScriptBlock(Page page, Boolean afterUI)   
Microsoft.SharePoint.WebControls.ScriptLink.Render(HtmlTextWriter writer)   

Local repro,

                string s = @"c:\blah\" + CultureInfo.CurrentCulture.LCID.ToString(CultureInfo.InvariantCulture) + "/" + "core.js?rev=123";
                FileIOPermission fp = new FileIOPermission(FileIOPermissionAccess.Append, s);

So, stick with <script> elements if need this performance trick. Another workaround is to keep using ScriptLink but on files deployed under /_layouts/, in which case this codepath is not traversed.