SharePoint 2013 memory issues
I’ve been working with SharePoint 2013 for a little while now and I’ve noticed some curious issues:
- When connecting to a site using SharePoint Designer 2013 I kept getting a message that the site contents could not be loaded. I actually had to stop SharePoint Designer via task manager since I kept getting the message boxes.
- When working with the Secure Store Service Application via code I got errors indicating the Secure Store was not started even though it was started according to the Services on Server page in Central Administration.
- When working with the Secure Store Service Application via code I got access denied errors on the web service call.
- When working with the Secure Store Service Application via code I got access denied errors on the web service call.
- When working with the Business Data Connectivity Service Application I got access denied errors on the web service call.
It took me a bit of time, but at the end I found out that these issues arose because of memory issues, or better the lack of available memory. When your SharePoint server uses 95% or more of its memory, web services can no longer be started. The problem I have with my development environment is that it’s a single server setup. SQL Server is running on the same VM and it was slowing eating all my available memory. By setting the maximum server memory I can avoid these issues luckily.
Replace characters in file names
A colleague of mine needed to migrate a file share with a lot of documents to SharePoint. During this process he ran into a problem. Lots of documents had a ‘&‘ character in the name, which is not allowed on SharePoint. During the large amount of files and the nesting of a large amount of folders, it was too much work to manually find all the files with this character and change their names. To make it a little bit easier, I’ve created the PowerShell script below. It might be useful to others as well J.
# Provide the name of the root folder
$folderWithFiles = “C:\Temp”
# Provide the character to replace
$charactersToReplace = “&”
# Provide the character to replace with
$charactersToReplaceWith = “_”
# When setting this value too false, no updates will be made, but the script will display the files containing the $charactersToReplace
$performUpdate = $false
# No changes need to be made below this
$filter = “*$charactersToReplace*”
function PerformReplace() {
$replacesMade = $false
get-childitem -recurse $folderWithFiles -Filter $filter | ForEach-Object {
if($performUpdate) {
rename-item $_.FullName -newname $_.Name.Replace($charactersToReplace,$charactersToReplaceWith)
Write-Host “The following file is renamed: “ $_.FullName -ForegroundColor DarkGreen
$replacesMade = $true
}
else {
Write-Host “The following file should be renamed: ” $_.FullName -ForegroundColor DarkRed
}
}
$replacesMade
}
# Keep running the script until no more changes have been made. When a replacement has been made
# in a folder name, the containing files will not be updated until the next loop.
function PerformReplaceUntilNoFilesFound() {
$replacesMade = $true
do {
$replacesMade = PerformReplace
}
while ($replacesMade -eq $true)
}
PerformReplaceUntilNoFilesFound
Optimizing your SharePoint development environment – Versioning
Today I’ve spent some time optimizing my Visual Studio settings in order to automatically update version numbers in my SharePoint projects. For this I’ve look at adding version numbers for assemblies and for solution packages.
In this post I’ll start by explaining the theory and I will end with how I’ve changed my Visual Studio settings.
The theory
Assembly versions
For assemblies, you have two different version numbers you could update.
- Assembly Version: This is the version number used by the .NET framework during build and at runtime to locate, link and load the assemblies. When you add reference to any assembly in your project, it is this version number which gets embedded. At runtime, CLR looks for assembly with this version number to load.
- Assembly File Version: This is the version number given to file as in file system. It is displayed by Windows Explorer. It’s never used by .NET framework or runtime for referencing.
Challenges with assemblies in WSP’s
Updating the assembly version number for your SharePoint solutions will provide you with some challenges. The main challenges are:
-
SharePoint stores assembly references including assembly version in many different places:
- ASPX
- C# Code
- Web Part XML
- Web Config
- Control Templates
- …
- Creating a new version would require a lot of additional work, since it would mean you need to modify a large number of files to update the assembly version and would require tooling to upgrade artifacts in the content databases.
SharePoint Solution Packages (WSP)
Solutions don’t have a version number included unless you add one in the name. It is recommended to add a version number, because this is the only way to know which version of your solution is deployed (only the name is listed in the solution overview page or when you check the installed solutions via PowerShell).
Important:The name is only used for displaying which solutions are installed, internally SharePoint uses the identifier of the solution (a GUID).
To be consistent with the naming conventions on features, add the namespace to the solution name too. For instance Peter.SP2010.Intranet.Core_v1.0.12177.wsp for a solution adding core functionality.
I use the following naming convention for solutions:
<Company>.SP2010.<ApplicationName>.<ApplicationBuildingBlock>_<version>.wsp
For example:
Peter.SP2010.Intranet.SiteDefinitions_v1.0.12177.wsp
Version numbers
Version numbers are written as:
<major>.<minor>.<build>.<revision>
I incremented the version numbers as followed:
- Major: A significant change to the UI or code base is reflected in the major number. This mainly happens when a complete new version of the solution has been created
- Minor: Providing a new release package with huge changes. This is something I tend to avoid, since I don’t want to update all versions numbers in non-code files.
- Build: Indicating which day of which year the build is made. The format for the build number is YYDDD. The YY is indicating the last two digits of the year and DDD is indicating the day of the year (1-365).
- Revision: Is used to indicate if the release is contains a bugfix. If the number is higher than 0 then that indicates that the release contains a bugfix from the same day.
The implementation
To update the AssemblyFileVersion and the solution naming, I’ve updated the project file manually and added a pre and post build event.
Ensure a package is created during the build event
Most times I perform a build, I also want the WSP file to be generated. To allow this, you can add the following XML to your project file:
<PostBuildEventDependsOn>
$(PostBuildEventDependsOn);
CreatePackage;
</PostBuildEventDependsOn>
This ensures that on every build action, a WSP is created as well. I need this file to update the name to include the version number in the next steps.
Update the AssemblyFileVersion
Notes
The following PowerShell script can be used to update the AssemblyFileVersion when building your project. Important items to note:
- The build events are triggered from the folder in which the assembly is build. So this will be either from [projectfolder]\bin\debug or [projectfolder]\bin\release.
- When using TFS, you should make sure the path to the Visual Studio folder containing tf.exe is added to the PATH environment variable and the line to check the file out should be enabled.
- I only update the AssemblyFileVersion when generating a release package. For debug on my development machine I don’t think it’s needed.
Usage
To use this script, please it somewhere on your development machine and then start it in a pre-build event (properties of your project > Build Events). In my case I start it as stated below. I use a relative path since it’s part of my TFS source and I don’t know the mapping of other developers:
if $(ConfigurationName) == Release powershell.exe ..\..\..\..\..\BuildScripts\UpdateFileVersionAssembly.ps1
The script
#------------------------------------------------------------------------------- # Displays how to use this script. #------------------------------------------------------------------------------- function Help { "Sets the AssemblyFileVersion of AssemblyInfo.cs files`n" ".\SetVersion.ps1 [VersionNumber]`n" " [VersionNumber] The version number to set, for example: 1.1.9301.0" " If not provided, a version number will be generated.`n" } #------------------------------------------------------------------------------- # Generate a version number. # Note: customize this function to generate it using your version schema. #------------------------------------------------------------------------------- function Generate-VersionNumber { $today = Get-Date return "1.0." + ( ($today.year - 2000) * 1000 + $today.DayOfYear )+ ".0" } #------------------------------------------------------------------------------- # Update version numbers of AssemblyInfo.cs #------------------------------------------------------------------------------- function Update-AssemblyInfoFiles ([string] $version) { $fileVersionPattern = 'AssemblyFileVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)' $fileVersion = 'AssemblyFileVersion("' + $version + '")'; $scriptPath = pwd $scriptPath = Split-Path -Path (Split-Path -Path $scriptPath -Parent) -Parent $scriptPath | Get-ChildItem -r -filter AssemblyInfo.cs | ForEach-Object { $filename = $_.Directory.ToString() + '\' + $_.Name $filename + ' -> ' + $version # If you are using a source control that requires to check-out files before # modifying them, make sure to check-out the file here. # Ensure the TFS command line tool is accessible #$env:Path =$env:Path + ";D:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\" # For example, TFS will require the following command: # tf checkout $filename (Get-Content $filename) | ForEach-Object { % {$_ -replace $fileVersionPattern, $fileVersion } } | Set-Content $filename } } #------------------------------------------------------------------------------- # Parse arguments. #------------------------------------------------------------------------------- if ($args -ne $null) { $version = $args[0] if (($version -eq '/?') -or ($version -notmatch "[0-9]+(\.([0-9]+|\*)){1,3}")) { Help return; } } else { $version = Generate-VersionNumber } Update-AssemblyInfoFiles $version
Update the Solution name
Notes
The following PowerShell script can be used to update the solution name when building your project. Important items to note:
- You should have updated the project file to generate a solution package on build.
- The build events are triggered from the folder in which the assembly is build. So this will be either from [projectfolder]\bin\debug or [projectfolder]\bin\release.
- The script makes a copy of the solution to a different location in my mapped source tree. Make sure the $copyPath is valid for you. If you just want to rename it, use Move-Item instead of Copy-Item.
Usage
To use this script, please it somewhere on your development machine and then start it in a post-build event (properties of your project > Build Events). In my case I start it as stated below. I use a relative path since it’s part of my TFS source and I don’t know the mapping of other developers:
if $(ConfigurationName) == Release powershell.exe ..\..\..\..\..\BuildScripts\UpdateWSPName.ps1
The script
#------------------------------------------------------------------------------- # Displays how to use this script. #------------------------------------------------------------------------------- function Help { "Sets the WSP name to include a version`n" ".\SetVersion.ps1 [VersionNumber]`n" " [VersionNumber] The version number to set, for example: 1.1.9301.0" " If not provided, a version number will be generated.`n" } #------------------------------------------------------------------------------- # Generate a version number. # Note: customize this function to generate it using your version schema. #------------------------------------------------------------------------------- function Generate-VersionNumber { $today = Get-Date return "1.0." + ( ($today.year - 2000) * 1000 + $today.DayOfYear )+ ".0" } #------------------------------------------------------------------------------- # Update version numbers of WSP file #------------------------------------------------------------------------------- function Update-WSPFile ([string] $version) { # Determine the paths $generatedPath = pwd $copyPath = pwd #$copyPath = Join-Path -Path (Split-Path -Path (Split-Path -Path (Split-Path -Path $copyPath -Parent) -Parent) -Parent) -ChildPath "\_deployment\WSP\" $generatedPath | Get-ChildItem -filter "*.wsp"| ForEach-Object { # Remove previous version from WSPFolder $copyPath | Get-ChildItem -filter ($_.Name.TrimEnd(".wsp") + "*.wsp") | ForEach-Object { remove-item $_.fullname } # Copy to deployment folder $filenameOld = $_.Directory.ToString() + "\"+ $_.Name $filenameNew = $copyPath.ToString() + "\" + $_.Name.TrimEnd(".wsp") + "_v" + $version + ".wsp" Copy-Item $filenameOld $filenameNew } } #------------------------------------------------------------------------------- # Parse arguments. #------------------------------------------------------------------------------- if ($args -ne $null) { $version = $args[0] if (($version -eq '/?') -or ($version -notmatch "[0-9]+(\.([0-9]+|\*)){1,3}")) { Help return; } } else { $version = Generate-VersionNumber } Update-WSPFile $version
Credits
I made some small changes to the script which you can find here: http://www.luisrocha.net/2009/11/setting-assembly-version-with-windows.html
Warm-up script for Form Based Authentication (FBA) SharePoint sites
Abstract
During a project we created a SharePoint environment which uses custom membership and claims providers. To make sure the first visitor in the morning doesn’t have to wait too long, we want to use a warm-up script. On the Internet there are a lot of warm-up scripts for SharePoint, but they mainly focus on SharePoint sites which use Active Directory as authentication source. I did find some executables which allow the warm-up of FBA SharePoint sites, but I prefer a PowerShell script. Mainly because a script will be readable by the administrators of the servers (current and future administrators) and they can see what happens.
Steps of form based authentication
If we look at the process of form based authentication, the following steps can be defined:

In order to mimic this process, the warm-up script will need:
- The URL of the site to warm-up.
- The URL which is used when redirecting. This is the URL you’ve set as login page for your authentication provider and you could add some query string variables for the return URL.
- The pages you actually want to hit. When you have pages which are really important and used cached data or something like that, you might want to pre load all of these pages.
When you have this in place, you might want to use an application like Fiddler to actually perform this process once. What you will need in the script, is the generated authentication cookie so you can actually login to your site and perform the warm-up. Not to worry, the script itself actually gathers almost all the information for you. The important pieces you will need from the login page are the __VIEWSTATE and __EVENTVALIDATION. These you’ll need to actually perform the login before you can warm-up your site. The script already retrieves this data from the page. The part you’ll need to paste in yourself is the ID’s you use for the login controls. This is also noted in the script itself.
The script
The script itself is pretty self-explanatory, there is plenty of commenting in it:
#———————————————————————————————————————-
# Add the System.Web assembly to allow the use of the web client
#———————————————————————————————————————-
Add-Type -AssemblyName System.Web
#———————————————————————————————————————-
# This method will call the site to warm up
#———————————————————————————————————————-
function WarmUpFBASite([string] $rootUrl, [string] $username, [string]$password,[string] $serverRelativeLoginUrl, [array] $serverRelativePageUrls){
# Build the complete login url
$loginUrl = $rootUrl + $serverRelativeLoginUrl
# Create a cookie container for the authentication cookie
$CookieContainer = New-Object System.Net.CookieContainer
# Retrieve the authentication cookie
$CookieContainer = RequestAuthenticationCookie -url $loginUrl -username $username -password $password
# Load all pages
foreach($relativeUrl in $serverRelativePageUrls) {
# Build the page url
$url = $rootUrl+ $relativeUrl
# Create a new request and add the properties for it
[net.httpWebRequest] $request = [net.webRequest]::create($url)
$request.Method = “GET”
$request.Accept = “text/html”
$request.AllowAutoRedirect = $false
$request.CookieContainer = $CookieContainer
# Determine which timeout you need
$request.TimeOut = 120000
# Get the response
[net.httpWebResponse] $response = $request.getResponse()
# Read the resonse stream
$responseStream = $response.getResponseStream()
$streamReader = new-object IO.StreamReader($responseStream)
# The result will hold the actually returned html
$result = $streamReader.ReadToEnd()
# Close the response steam
$streamReader.Close()
}
}
#———————————————————————————————————————-
# This method retreives the authentication cookie
#———————————————————————————————————————-
function RequestAuthenticationCookie([string] $url, [string] $username, [string]$password) {
# Create a new cookie container
$CookieContainer = New-Object System.Net.CookieContainer
# Get the post data needed for the request.
$postData = GetPostData -url $url -username $username -password $password
# Place the post data object in the buffer
$buffer = [text.encoding]::ascii.getbytes($postData)
# Open a new request and set the properties
[net.httpWebRequest] $req = [net.webRequest]::create($url)
$req.method = “POST”
$req.Accept = “image/jpeg, image/gif, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*”
$req.Headers.Add(“Accept-Language: en-US”)
$req.Headers.Add(“Accept-Encoding: gzip,deflate”)
$req.Headers.Add(“Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7″)
$req.AllowAutoRedirect = $true
$req.ContentType = “application/x-www-form-urlencoded”
$req.ContentLength = $buffer.length
$req.TimeOut = 120000
$req.KeepAlive = $true
$req.Headers.Add(“Keep-Alive: 300″);
$req.CookieContainer = $CookieContainer
$requestStream = $req.getRequestStream()
$requestStream.write($buffer, 0, $buffer.length)
$requestStream.flush()
$requestStream.close()
# Get the response
[net.httpWebResponse] $response = $req.getResponse()
$responseStream = $response.getResponseStream()
$streamReader = new-object IO.StreamReader($responseStream)
$result = $streamReader.ReadToEnd()
$response.close()
# Return the cookie
$CookieContainer
}
#———————————————————————————————————————-
# This method retreives the postdata needed to retrieve the authentication cookie
#———————————————————————————————————————-
function GetPostData ([string] $url, [string] $username, [string]$password) {
# Open a new web client
$webClient = New-Object System.Net.WebClient
$webClient.Headers.Add(“user-agent”, “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)”)
$data = $webClient.OpenRead($url)
$reader = New-Object System.IO.StreamReader($data)
$result = $reader.ReadToEnd()
$data.Close()
$reader.Close()
# Retrieve the view state
$viewState = ExtractPostDataElements -source $result -hiddenInputName “__VIEWSTATE”
# Retrieve the event valudation
$eventValidation = ExtractPostDataElements -source $result -hiddenInputName “__EVENTVALIDATION”
# Be aware, in the postdata also the ID’s of the login controls are placed. You will have to look in your login page and replace the values in the string below!
$postData = “__LASTFOCUS=&__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=$viewstate&__EVENTVALIDATION=$eventValidation&ctl00%24PlaceHolderMain%24signInControl%24UserName=$username&ctl00%24PlaceHolderMain%24signInControl%24Password=$password&ctl00%24PlaceHolderMain%24signInControl%24LoginButton=Log+In”
# Return the post data object
$postData
}
#———————————————————————————————————————-
# This method retrieves post data elements and is used to retrieve the viewstate and eventvalidation objects
#———————————————————————————————————————-
function ExtractPostDataElements ([string] $source, [string] $hiddenInputName) {
$valueDelimiter = “value=`”"
$inputNamePosition = $source.IndexOf($hiddenInputName)
$inputValuePosition = $source.IndexOf($valueDelimiter, $inputNamePosition)
$inputStartPosition = $inputValuePosition + $valueDelimiter.Length
$inputEndPosition = $source.IndexOf(“`”", $inputStartPosition)
$inputElement = [System.Web.Httputility]::UrlEncode($source.Substring($inputStartPosition, $inputEndPosition - $inputStartPosition))
$inputElement
}
#———————————————————————————————————————-
# Call the warmup methods
#———————————————————————————————————————-
WarmUpFBASite -rootUrl “http://www.sharepoint.local” -userName “” -password “” `
-serverRelativeLoginUrl “/_layouts/testproject/CustomLoginPage.aspx?ReturnUrl=%2f_layouts%2fAuthenticate.aspx%3fSource%3d%252F&Source=%2F” `
-serverRelativePageUrls (“/Pages/default.aspx”,“/subsite/Pages/default.aspx”)
PowerShell – Delete field and all references
Sometimes you want to delete a site column from SharePoint and you get the nice message stating “Site columns which are included in content types cannot be deleted. Remove all references to this site column prior to deleting it.”. Really helpful that it states in which ContentTypes the field is used. It gets even worse when the column is also used in lists… You can do this via PowerShell easily:
# Add SharePoint PowerShell Snapin
if ( (Get-PSSnapin -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null ) {
Add-PSSnapin Microsoft.SharePoint.Powershell
}
#—————————————————————————-
# Delete Field
#—————————————————————————-
function DeleteField([string]$siteUrl, [string]$fieldName) {
Write-Host “Start removing field:” $fieldName -ForegroundColor DarkGreen
$site = Get-SPSite $siteUrl
$web = $site.RootWeb
#Delete field from all content types
foreach($ct in $web.ContentTypes) {
$fieldInUse = $ct.FieldLinks | Where {$_.Name -eq $fieldName }
if($fieldInUse) {
Write-Host “Remove field from CType:” $ct.Name -ForegroundColor DarkGreen
$ct.FieldLinks.Delete($fieldName)
$ct.Update()
}
}
#Delete column from all lists in all sites of a site collection
$site | Get-SPWeb -Limit all | ForEach-Object {
#Specify list which contains the column
$numberOfLists = $_.Lists.Count
for($i=0; $i -lt $_.Lists.Count ; $i++) {
$list = $_.Lists[$i]
#Specify column to be deleted
if($list.Fields.ContainsFieldWithStaticName($fieldName)) {
$fieldInList = $list.Fields.GetFieldByInternalName($fieldName)
if($fieldInList) {
Write-Host “Delete column from ” $list.Title ” list on:” $_.URL -ForegroundColor DarkGreen
#Allow column to be deleted
$fieldInList.AllowDeletion = $true
#Delete the column
$fieldInList.Delete()
#Update the list
$list.Update()
}
}
}
}
# Remove the field itself
if($web.Fields.ContainsFieldWithStaticName($fieldName)) {
Write-Host “Remove field:” $fieldName -ForegroundColor DarkGreen
$web.Fields.Delete($fieldName)
}
$web.Dispose()
$site.Dispose()
}
#Delete the field below
DeleteField http://sharepoint “MyField”
SharePoint Connection Netherlands 2011
On 22 and 23 November 2011 the SharePoint Connections 2011 was held in Amsterdam. I gave a session on Visio Services and Visio Services Development. The presentation and the files used you can download here.
SharePoint cache settings when restyling
When restyling web applications, you have to think of the cache settings which are set to the different resource files, since you want people to see the new styles without having to clear their local cache. These files for example can be:
- Style Sheets
- Images
- Java Scripts
If we for example open a normal team site and open up Fiddler, we will see how long the files are cached (you might want to first clear your cache or use a hard refresh to force all files to download).

Figure 1: Default Team Site

Figure 2: Fiddler trace of the loading of the default Team Site
When you look at the Fiddler trace, you can see the following cache settings:
- The aspx file is not cached.
- The Java Scripts are cached for a year.
- The style sheets are cached for a year.
- The images are cached for a year.
The reason for this is that the newly created web site, the content expiration is not enabled for the web site itself, but it is enabled for the four virtual directories:
- _controltemplates
- _layouts
- _vti_bin
- _wpresources
For the virtual directories the default setting is to enable content expiration for 365 days.

Figure 3: By default the settings for the Web Site is to not use content expiration

Figure 4: The default setting for the _layouts folder is to use content expiration for 365 days
These default cache settings can be updated, but otherwise this means: You can NOT simply update your resources in the _layouts folder and expect your users to see the update immediately!
Possible solutions
To overcome the caching problems, there are multiple solutions. For example:
- Use new filenames
- Use new directory
- Use a query string
Use new filenames
The first possible solution is to simply rename all the files you are changing during the restyling of SharePoint. This will allow you to bypass the client side cache. You will however need to:
- Rename all the files you store in the _layouts folder which have changed.
- Find and update all the filenames you refer to inside your Java Scripts, if they are stored in the _layouts folder.
- Find and update all the filenames (f.e. images) you refer to inside your Style Sheets, if they are stored in the _layouts folder.
- Find and update all the filenames you refer to inside your code, if they are stored in the _layouts folder.
- Find and update all the filenames you refer to inside your master pages, if they are stored in the _layouts folder.
- Find and update all the filenames you refer to inside your pages, if they are stored in the _layouts folder.
- Find and update all the filenames you refer to inside your control templates, if they are stored in the _layouts folder.
- Etc.
The downside here is you have to search for every file individually, which can be time consuming and error prone.
Use new directories
When storing your own files in the _layouts folder, a best practice is to use your own subfolders. An option would be to rename all your subfolders in the _layouts folder. That would bypass the client side cache. For this you will need to:
- Rename all the directories you store in the _layouts folder
- Find and update all the filenames you refer to inside your Java Scripts, if they are stored in the _layouts folder
- Find and update all the filenames (f.e. images) you refer to inside your Style Sheets, if they are stored in the _layouts folder
- Find and update all the filenames you refer to inside your code, if they are stored in the _layouts folder.
- Find and update all the filenames you refer to inside your master pages, if they are stored in the _layouts folder.
- Find and update all the filenames you refer to inside your pages, if they are stored in the _layouts folder.
- Find and update all the filenames you refer to inside your control templates, if they are stored in the _layouts folder.
- Etc.
This method is easier than the one above (using new file names), since you can do a find/replace on your solutions and just replace the directory name. You will however need to update the directory naming and probably the relevant documentation.
Use a query string
Another option is to use a query string after the resource files you are using. This is actually how SharePoint internally solves the issue as well:
Figure 5: Page source of default Team Site
Within SharePoint you can let the query string “?rev=xxxxxxxxxxxxxx” be generated automatically by using the SPUtility.MakeBrowserCacheSafeLayoutsUrl. This function will place “_layouts/” before and “?rev=[some string here]” after a given string. This however is a server side action which would in turn be triggered for every resource you use. This is a load on the system which can be avoided. Another downside of this function is that it will only work for files stored in the layouts folder on the file system. This means it will not work for the images folder. Besides that, this might work in your code files, master pages and aspx pages, but you’ll have to jump through a couple of hoops to get this working in style sheets and java scripts!
What we in turn did was placing a string like “?rev=201003221230″ after all loaded resources. The number is actually a timestamp from when we started on the change. This means you’ll have to:
- Find and update all the filenames you refer to inside your Java Scripts, if they are stored in the _layouts folder
- Find and update all the filenames (f.e. images) you refer to inside your Style Sheets, if they are stored in the _layouts folder
- Find and update all the filenames you refer to inside your code, if they are stored in the _layouts folder.
- Find and update all the filenames you refer to inside your master pages, if they are stored in the _layouts folder.
- Find and update all the filenames you refer to inside your pages, if they are stored in the _layouts folder.
- Find and update all the filenames you refer to inside your control templates, if they are stored in the _layouts folder.
- Etc.
But the benefits are:
- With a next rebranding you can easily do a replace all on the string “?rev=201003221230″ on your solution.
- You don’t have to keep track of which files you actually modified.
- No additional actions on the server are needed.
- It works for every file type.