0

I have a SharePoint 2013 Server in a test environment at my customer. It is filtered through a cache instance called Net Scaler, which does a good job delivering the same file to different clients. The problem is that it doesn't check if the file is new - it just pushes out what it got.

Adding a css-variable such as styles.css?ver=1000 solves the problem, and Net Scaler considers this as a new file. However, I'm having trouble making this unique on each page request.

Since this is SharePoint 2013, I'm not allowed to edit code behind and is limited to the .master file. I've tried different markups, but nothing that works the way I expect it.

This is my attempt so far, but it doesn't work as expected.

<SharePoint:CssRegistration 
name="/_catalogs/masterpage/Customer/Style/ResponsiveMaster.css?ver=
<%= DateTime.Now.ToString() %>" runat="server" after="SharepointCssFile" />

<!-- or -->

<link rel="stylesheet" type="text/css"
href="/_catalogs/masterpage/Customer/Style/ResponsiveMaster.css?ver=
<%= DateTime.Now.ToString() %>"  />

I even tried loading the css-file using inline JavaScript from this post How to load up CSS files using Javascript?:

<script type="text/javascript">
    //<![CDATA[ 
        var $ = document; // shortcut
        var timestamp = Date.now();
        var cssId = '/_catalogs/masterpage/Customer/Style/ResponsiveMaster.css?ver=' + timestamp;  
        // you could encode the css path itself to generate id..
        if (!$.getElementById(cssId))
        {
            var head  = $.getElementsByTagName('head')[0];
            var link  = $.createElement('link');
            link.id   = cssId;
            link.rel  = 'stylesheet';
            link.type = 'text/css';
            link.href = '/_catalogs/masterpage/Customer/Style/ResponsiveMaster.css?ver=' + timestamp;
            link.media = 'all';
            head.appendChild(link);
        }
    //]]>
</script>

But no luck there either.

Community
  • 1
  • 1
Benny Skogberg
  • 10,431
  • 11
  • 53
  • 83

2 Answers2

5

Placing the following markup in the .Master page:

<link rel="stylesheet" 
       href=<%="'css/main.css?v="+ DateTime.Now.ToString("yyyyMMddhhmmss") +"'"%> />

To allow inline code blocks in sharepoint, as per this blog post you'll need to modify your web.config. Replace the PageParser section with the code below:

<PageParserPaths >
  <PageParserPath VirtualPath="/*" CompilationMode="Always"   
                  AllowServerSideScript="true" IncludeSubFolders="true" />
</PageParserPaths>

Will produce the following output in the browser:

   <link rel="stylesheet"  href='css/main.css?v=20140123113734' />
Aheho
  • 12,622
  • 13
  • 54
  • 83
  • Looks interesting, I'll notice you in a couple of hours if this works. Thanks for trying! – Benny Skogberg Jan 24 '14 at 05:41
  • No luck. I got this in return **Sorry, something went wrong An error occurred during the processing of** `/_catalogs/masterpage/Customer/Responsive.master`. **Code blocks are not allowed in this file.** – Benny Skogberg Jan 24 '14 at 07:20
2

I looked at the NetScaler documentation and it says it will obey cache control headers if not configured to ignore them. So you could try to serve your CSS with headers which disable caching. You'll have to do this using a generic handler.

Create a generic handler (.ashx) and add this code to the ProcessRequest method:

context.Response.AddHeader("Cache-Control", "no-cache, no-store, must-revalidate");
context.Response.AddHeader("Pragma", "no-cache");
context.Response.AddHeader("Expires", "0");
context.Response.ContentType = "text/css";            
context.Response.WriteFile(context.Server.MapPath("~/_catalogs/masterpage/Customer/Style/ResponsiveMaster.css"));

You can also try setting the cache control header using a child web.config file in your css folder:

<configuration>
  <system.webServer>
    <staticContent>
      <clientCache cacheControlCustom="no-cache"/>
    </staticContent>
  </system.webServer>
</configuration>
Jay Douglass
  • 4,828
  • 2
  • 27
  • 19