Partilhar via


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.

Comments

  • Anonymous
    April 30, 2012
    Or you could just do this perhaps instead of changing it to <script> element:<SharePoint:ScriptLink id="ScriptLink1" language="javascript" name='<%# "Core.js?ver=" + Helper.CurrentAssemblyVersion %>' runat="server" />