Upgrading Sandbox Solutions in SharePoint


In SharePoint 2013 for online solutions there is only two choices for deploying custom code now, using apps, or Sandbox solutions. Now, Microsoft has stated that Sandbox solutions have been deprecated in 2013 version of SharePoint, but this is only for assemblies running on the Sandboxed Code Service. Therefore JavaScript, WebTemplates, elements and Manifest files are still valid to use in your sandbox solutions.

For a while now I have been building Sandbox solutions in SharePoint 2013, luckily, most projects I have worked on are Day 1 implementations. Therefore, I’ve never really needed to worry about upgrades. Just deactivate, retract, remove, add, deploy, activate until I get it right. Problem is after day 1 you no longer have the luxury to remove and re-add again. There is content on the site, a list with data in. You remove it you will have some unhappy customers.

I’m going to build a sample solution and upgrade it twice. This example doesn’t actually do anything useful apart from show you the correct way to upgrade. You can download the visual studio project and the wsp’s of each version from my One Drive. (Please note I’m certain this will work without issue on SharePoint Online, however, I wrote and tested this code only on an on premise server.)

Building Version 1

In this initial project build, I’m going to be adding the following:

  • Custom Actions – Adds JQuery and a JavaScript file.
  • Column – Add a choice column
  • Content Type – Custom Content type, based on Document Library with my additional choice column.
  • Assets – Logo file, my custom JavaScript file, jQuery library

The solution looks like the following:

I will put the XML/code for each custom file below, I will not include jquery-1.11.1.min.js code.

  • CA_JQuery (Elements file) – Custom actions that add Jquery link and my own custom JavaScript.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction ScriptSrc="~sitecollection/assets/jquery-1.11.1.min.js"
                Location="ScriptLink"
                Sequence="100">
  </CustomAction>
  <CustomAction ScriptSrc="~sitecollection/assets/CFUpgrade.js"
                Location="ScriptLink"
                Sequence="101">
  </CustomAction>
</Elements>
  • CO_Classification (Elements file) –Choice column, with a default option.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Field
       ID="{815f2492-94b7-43a9-b679-2b3cbaaa35bf}"
       Name="CO_Classification"
       DisplayName="Classification"
       Type="Choice"
       Required="FALSE"
       Group="Cannonfodder">
    <Default>Standard</Default>
    <CHOICES>
      <CHOICE>Standard</CHOICE>
      <CHOICE>Important</CHOICE>
      <CHOICE>Secure</CHOICE>
    </CHOICES>
  </Field>
</Elements>
  • CT_Document (Elements file)
    Content Type based on Document Library containing Classification Column.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- Parent ContentType: Document (0x0101) -->
  <ContentType ID="0x0101004A6AC4D7159D498DBDF17D3C10D609A0" Name="CannonFodder Document" Group="CannonFodder" Description="A Document type just for Cannonfodder" Inherits="TRUE">
    <FieldRefs>
      <FieldRef ID="{815f2492-94b7-43a9-b679-2b3cbaaa35bf}" DisplayName="Classification" Required="FALSE" Name="CO_Classification" />
    </FieldRefs>
  </ContentType>
</Elements>
  • CFUpgrade.js Custom Javascript file which changes the site icon to display the Cannonfodder.jpg
jQuery(document).ready(function () {
    jQuery('.ms-siteicon-img').attr("src", _spPageContextInfo.webAbsoluteUrl + "/assets/Cannonfodder.jpg");
});
  • Assets (Elements file) – Manifest file which tells SharePoint to deploy file to a folder called Assets. Ensure all files have attribute ReplaceContent=”TRUE”.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="Assets">
    <File Path="Assets\CFUpgrade.js" Url="Assets/CFUpgrade.js" ReplaceContent="TRUE" />
    <File Path="Assets\Cannonfodder.jpg" Url="Assets/Cannonfodder.jpg" ReplaceContent="TRUE" />
    <File Path="Assets\jquery-1.11.1.min.js" Url="Assets/jquery-1.11.1.min.js" ReplaceContent="TRUE" />
  </Module>
</Elements>

Add all the SharePoint Items to the feature, and ensure the feature is a scoped for Site. Publish it as a WSP. Then the solution can be upload it to SharePoint and activate. It is not recommended using Visual Studio to do your deployments on your dev environments. The main reason is because Visual Studio will retract and remove the solution if it currently exists in SharePoint, which means you are never upgrading the solution. (Not really an issue for Version 1, but best get use to it.) By right clicking the project and selecting Publish… from the context menu, you can then package up the project to a location on the hard drive.

Personally I will rename this file solutionName_v1.0.0.0.wsp. Until I know the code is right, this will always be version 1.0.0.0. Also note that the Solution number doesn’t have to correspond to the feature version, mainly because most solutions will have multiple features in them. I’m keeping them the same so that it logically make sense to you while following this blog post.

Steps to upload a Sandbox Solution

I always try and write my blogs as if I’m teaching someone for the first time especially for the parts that are related to the topic, so here are the steps to add the solutions.

  • Go to the site (I’ve created a clean Team Site, Site collection).
  • Site Actions (cog) -> Site Settings
  • Under Web Designer Galleries, Click Solutions


  • Click Upload Solution on the ribbon bar.
  • On the Add a Document dialog browse for the wsp file created, Click OK.
  • On the ribbon bar of the new dialog, Click Activate.


  • The solution has now been installed to that Site Collection. If the feature was configured to Activate On Default the column, content type, asset files will already deployed and working on the site, otherwise the feature will need activating.


How does the site currently look.


From looking at the homepage, we can see the SharePoint Icon has changed to my CannonFodder picture. Which indicates that my custom action, JQuery and custom Javascript file has loaded and working. Can also double check by looking at the Internet Explorer Dev tools (F12) and check that the scripts have loaded.


If we look at the content types Site Actions > Site Settings > Web Designer Galleries > Site content types, the Content Type CannonFodder Document is there.


And the content type contains our Classification Column.

To ensure that this content type works, I’m going to add my content type to the document library and upload a document and set the classification column.

  • Go to the document library.
  • Select Library on the ribbon bar and then Library Settings
  • In Settings, under General Settings Click Advanced settings
  • At the top of the page, set Allow management of content types to Yes. Scroll down and Click
    OK.
  • Under Content Types, click Add from existing site content types.
  • Find and Add CannonFodder Document and then Click OK.
  • Remove Document Content type, by click on Document and then Delete this content type.
  • Under Views click All Documents. Add the Classification column to the view. Click OK.
  • Add document by clicking (+) new document. Browse to find a Word Document.
  • On the Metadata dialog, there will be Name, Title and Classification available. Click Save.

Building Version 2

Now that I have deployed my code, a document has been uploaded using my content type. The site is being used. Removing the solution and installing a new version of the solution could cause damage to the site, or worse, not even install, leaving the site in a state of flux. Not quite a working version 1, not quite a working version 2.

Changes for Version 2:

  • A new custom column – hyperlink URL field called Source
  • Update Content Type to include new custom column
  • A new custom action to insert CSS into the page.
  • Update the Cannonfodder.jpg logo to a better picture.
  • A new CSS file.
  • Additional JavaScript code added to the CFUpgrade.js file.

     

The solution now looks like the following:

I will put the XML/code for each custom added or been upgraded

  • CO_Source(Elements file) –URL Column. (NEW)
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Field
       ID="{b952f5fd-8490-49f6-8b02-cdf4cfc03a99}"
       Name="CO_Source"
       DisplayName="Source"
       Type="URL"
       Format="Hyperlink"
       Required="FALSE"
       Group="Cannonfodder">
  </Field>
</Elements>
  • CT_Document (Elements file) – Adds Source column (Upgrade)
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- Parent ContentType: Document (0x0101) -->
  <ContentType ID="0x0101004A6AC4D7159D498DBDF17D3C10D609A0" Name="CannonFodder Document" Group="CannonFodder" Description="A Document type just for Cannonfodder" Inherits="TRUE">
    <FieldRefs>
      <FieldRef ID="{815f2492-94b7-43a9-b679-2b3cbaaa35bf}" DisplayName="Classification" Required="FALSE" Name="CO_Classification" />
      <FieldRef ID="{b952f5fd-8490-49f6-8b02-cdf4cfc03a99}" DisplayName="Source" Required="FALSE" Name="CO_Source" Format="Hyperlink" />
    </FieldRefs>
  </ContentType>
</Elements>
  • CA_Css (Elements file) – Adds CSS to the page (New)
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="ReferCssSiteCol" Location="ScriptLink"
                ScriptBlock="document.write('&lt;link rel=&quot;stylesheet&quot; After=&quot;Corev15.css&quot;  type=&quot;text/css&quot; href=&quot;~sitecollection/assets/CFStyle.css&quot;&gt;&lt;/' + 'link&gt;');"
                Sequence="202" />
</Elements>
  • Cannonfodder.jpgreplaced with new file with same name (Upgrade)
  • CFStyle.cssA css file that won’t win any styling awards (New)
#contentBox{
    background-color: aquamarine;
}
  • CFUpgrade.js A change adding additional JavaScript (Upgrade)
jQuery(document).ready(function () {
    jQuery('.ms-siteicon-img').attr("src", _spPageContextInfo.webAbsoluteUrl + "/assets/Cannonfodder.jpg");
    jQuery('#suiteBarLeft').css("background-Color", "darkred");
});
  • Assets (Elements file) – Add the extra files (Upgrade)
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="Assets">
    <File Path="Assets\CFUpgrade.js" Url="Assets/CFUpgrade.js" ReplaceContent="TRUE" />
    <File Path="Assets\jquery-1.11.1.min.js" Url="Assets/jquery-1.11.1.min.js" ReplaceContent="TRUE" />
    <File Path="Assets\Cannonfodder.jpg" Url="Assets/Cannonfodder.jpg" ReplaceContent="TRUE" />
    <File Path="Assets\CFStyle.css" Url="Assets/CFStyle.css" ReplaceContent="True"/>
 </Module>
</Elements>

Add all the extra SharePoint Items to the site feature.

This seems like all I need to do, publish the WSP again, rename it with the correct version and upload the new version to the solution file. It’s not. However some people think that is it, and before I show you what step they are missing let me go through the upgrade process they go through.

Note:
You have to rename the file differently to how the last wsp was named. It doesn’t have to be version numbers, but it has to be different, as you cannot have two solutions with the same name in a solution library. SharePoint will know that the wsp being uploaded is an Upgrade of the previous solution because the Solution ID’s will be the same. Why this solution library couldn’t use versioning is anyone guess.

Steps not to correctly upgrade a Sandbox Solution

  • After you have published the wsp file, rename it (For this example, mine is name CFUpgradeSolution_v2.0.0.0withoutupgrade)
  • Go to the site.
  • Site Actions (cog) -> Site Settings
  • Under Web Designer Galleries, Click
    Solutions
  • Click Upload Solution on the ribbon bar.
  • On the Add a Document dialog browse for the wsp file created, Click
    OK.
  • On the ribbon bar of the new dialog, Click Upgrade. Note how SharePoint recognises that this solution is to be upgraded and not a new solution, this is due to the solution ID remaining the same in both named wsp’s


  • After the upgrade, navigate to the home page.

So what has happened? Nothing.

At this point, some people then go to the Feature that’s got the changes in them, deactivate the feature and reactivate it again. Well that does seem to work, The CSS has been applied, my logo has been replaced with a much cooler image, the suite bar is now a dark red instead of Microsoft Blue, and my new site column is there.

However, my content type hasn’t been updated.

So we can see that some upgrade worked, and some didn’t.

I’m going to reset my site (create team site, apply CFUpgrade_v1.0.0.0.wsp, and follow my instructions to apply content type to document library)

Updating the Feature Manifest steps to correctly upgrade a Sandbox Solution

The step that is missing from the previous step is updating the Feature Manifest file, and giving your feature a version number.

  • Select the feature in the solution and open up the properties window (F4)
  • At the bottom of the properties window (if properties are in alphabetically order) you will find Version. When nothing is entered into this property, SharePoint will read the version as 0.0.0.0. As this is the second version of the feature I’m putting version 2.0.0.0
    Now we need to update the features manifest file to indicate what needs to be upgraded.
  • Click on the feature to open it, then Click on the Manifest
    tab.
  • At the bottom, on the Manifest tab, Click the plus button of Edit Options.

    This area allows you to add more XML to your Feature. It is here we will add an <UpgradeActions>
    http://msdn.microsoft.com/en-us/library/office/ff595308(v=office.15).aspx. The XML to add here will be merged into the current feature manifest XML by Visual Studio. The feature manifest XML will not appear in the preview box above the edit options if the XML is malformed. The current Feature Manifest XML has all our new files within it, which is required if this solution is added for the first time to a site, however we need to apply an <UpgradeActions> with the given <VersionRange>.

    The <VersionRange> indicates to SharePoint what previous version to apply this update to. If the feature currently installed within SharePoint doesn’t fall between these version range numbers, then it will not be upgraded.

    Any <ElementManifest> files listed will be re-applied or added if it is their first time being run in the feature. This is the reason why we added all our files with the attribute ReplaceContent=”TRUE”, because it will re-apply the files over the top of the original files.

    The <AddContentTypeField> allows the addition of extra columns to existing content types, and if stated, will push down the column to any Lists that are currently using that content type.

    In the Edit Option area between <Feature xmlns=”http://schemas.microsoft.com/sharepoint/”></Feature&gt; add the following.

<UpgradeActions>
   <VersionRange BeginVersion="0.0.0.0" EndVersion="1.9.9.9">
     <ApplyElementManifests>
        <ElementManifest Location="CO_Source\Elements.xml"/>
        <ElementManifest Location="CA_Css\Elements.xml"/>
        <ElementManifest Location="Assets\Elements.xml"/>
     </ApplyElementManifests>
     <AddContentTypeField ContentTypeId="0x0101004A6AC4D7159D498DBDF17D3C10D609A0" FieldId="{b952f5fd-8490-49f6-8b02-cdf4cfc03a99}" PushDown="TRUE"/>
   </VersionRange>
 </UpgradeActions>

The above states that any feature versions starting with 0.0.0.0 (which was our first deployment) to any feature version ending with 1.9.9.9 that we should do the following.

  • Re-Apply/Add CO_Source\Elements.xml
  • Re-Apply/Add CA_CSS\Elements.xml
  • Re-Apply/Add Assets\Elements.xml
  • Add the field with the given ID, to the given content type and push down to all lists using that content type. (CO_Source column add to CannonFodder Document)

Now you can go through the steps of Publishing the Solution, renaming to v2.0.0.0 and upgrading the feature.

  • After you have published the wsp file, rename it (For this example, mine is name CFUpgradeSolution_v2.0.0.0)
  • Go to the site.
  • Site Actions (cog) -> Site Settings
  • Under Web Designer Galleries, Click
    Solutions
  • Click Upload Solution on the ribbon bar.
  • On the Add a Document dialog browse for the wsp file created, Click
    OK.
  • On the ribbon bar of the new dialog, Click Upgrade. Note how SharePoint recognises that this solution is to be upgraded and not a new solution, this is due to the solution ID remaining the same in both named wsp’s

After you have clicked Upgrade, and SharePoint has processed your solution, you should notice that the upgrade has taken place without the need to deactivate and re-activate the feature.

If you navigate to your home page, and view the properties of the document you added to the document library earlier, you will notice you now have the extra column Source.

Which means the CannonFodder Document content type has also been updated correctly.

Building Version 3

My last and final version in this demo is to show how to build a feature that will work for a brand new instance directly to version 3. That it will work and upgrade a version 1 to version 3, and that it will upgrade a version 2 to version 3.

Changes for Version 3:

  • A new List Definition that uses the CannonFodder Document content type.
  • A new web feature with a List Instance.
  • Change the JQuery file so that the Suite Bar is bright Red.

The solution now looks like the following:

The code for the CFUpgrade JavaScript file is below.

  • CFUpgrade.js A change adding additional JavaScript (Upgrade)
jQuery(document).ready(function () {
    jQuery('.ms-siteicon-img').attr("src", _spPageContextInfo.webAbsoluteUrl + "/assets/Cannonfodder.jpg");
    jQuery('#suiteBarLeft').css("background-Color", "red");
});

To create the List Definition and Instance

  • Right Click on the solution > Add > New Item
  • Select List and name it. (I’ve named my CF_Document). Click Add.
  • Give a display name, and Create a customizable list template and a list instance of it: and select Document Library

  • Click Next > , then Finish
  • On the GUI version of the List Definition, Click
    Content Types button.
  • Click where it says Click here to add a content type
    and add CannonFodder Document.
  • Highlight CannonFodder Document and then Click Set as Default button. Click OK.
  • Now the columns Classification and Source should be appearing in the Column tabs.

  • Click on the Views tab and Add Classification and Source as Selected columns to All Documents view.
  • Open the Elements.xml file of the List Definition and change the Type to 101. (I have found since doing this to document libraries, the ribbon, buttons and text reflects how Microsoft Document library works).
<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <ListTemplate
        Name="CF_Document"
        Type="101"
        BaseType="1"
        OnQuickLaunch="TRUE"
        SecurityBits="11"
        Sequence="110"
        DisplayName="Cannonfodder Documents"
        Description="A list definition for Cannonfodder Document Content Types"
        Image="/_layouts/15/images/itdl.png"
        DocumentTemplate="121"/>
</Elements>
  • Open the Elements.xml file of the List Instance and change the TemplateType to 101. Also get the ID of the Site – CFUpgrade feature, and add this to the List Instance Elements file. This tells the elements file where to find the Definition file.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ListInstance Title="Cannonfodder Document Library"
                OnQuickLaunch="TRUE"
                TemplateType="101"
                Url="Lists/CannonfodderDocuments"
                FeatureId="87a3dfff-41d2-48fc-b919-a576103b7df9"
                Description="My List Instance">
</ListInstance>
</Elements>
  • Lastly don’t forget to add the List Definition to the Site Feature.
  • Create a new Feature, by Right Clicking
    Features and Add Feature. Set this feature to Web and add the List Instance to it.

Note:The reason why I have added the list instance to another feature was mainly because I couldn’t get the List Instance to create itself if the feature was being upgraded from Version 1 to Version 3. However, if I was upgrading from Version 2 to Version 3, the list instance appeared fine.

Updating the Feature Manifest steps

  • Select the Site feature in the solution and open up the properties window (F4)
  • At the bottom of the properties window (if properties are in alphabetically order) you will find Version. As this is the third version of the feature I’m putting version 3.0.0.0

    Now we need to update the features manifest file to indicate what needs to be upgraded.
  • Double Click on the feature to open it, then Click on the Manifest tabs
  • At the bottom, on the Manifest tab, Click the plus button of Edit Options.
    Now we need to ensure that any Version 1 of the feature is upgraded to have all the new files/content types etc of Version 2. Therefore the previous UpgradeAction we will leave. An additional <VersionRange> will be added to our manifest file to perform upgrade from Version 2 to Version 3.
  • In the Edit Option area between <Feature xmlns=”http://schemas.microsoft.com/sharepoint/”></Feature&gt; but after the last </VersionRange> add the following.
    <VersionRange BeginVersion="1.9.9.9" EndVersion="2.9.9.9">
    <ApplyElementManifests>
    <ElementManifest Location="Assets\Elements.xml"/>
     <ElementManifest Location="CF_Document\Elements.xml"/>
     </ApplyElementManifests>
    </VersionRange>
    

The above states that any feature versions starting with 1.9.9.9 (which was our second deployment) to any feature version ending with 2.9.9.9 that we should do the following.

  • Re-Apply/Add Assets\Elements.xml
  • Add CF_Document\Elements.xml (our list definition)

Now you can go through the steps of Publishing the Solution, renaming to v3.0.0.0 and upgrading the feature.

  • After you have published the wsp file, rename it (For this example, mine is name CFUpgradeSolution_v3.0.0.0)
  • Go to the site.
  • Site Actions (cog) > Site Settings
  • Under Web Designer Galleries, Click
    Solutions
  • Click Upload Solution on the ribbon bar.
  • On the Add a Document dialog browse for the wsp file created, Click
    OK.
  • On the ribbon bar of the new dialog, Click Upgrade. Note how SharePoint recognises that this solution is to be upgraded and not a new solution, this is due to the solution ID remaining the same in both named wsp’s

     

  • After you have clicked Upgrade, and SharePoint has processed your solution, you should notice that the upgrade has taken place without the need to deactivate and re-activate the feature as expected. The suite bar is now a bright red.

  • Site Actions (cog) > Site Settings
  • Under Site Actions, Click Manage Site Features
  • Click Activate on CF Upgrade Web Feature

In the quick link navigation on the left hand side, you should see Cannonfodder Document Library. Click on this link.

We can upload new document files here, and our view has the two new columns ready for us.

  • Click on Site Contents
  • Click on add an app
  • There is a new app called Cannonfodder Documents, which you can create a list of our list definition as many times you like.

Jumping between versions.

With the code that has been implemented above, there would be no problem creating a new site and installing version 3. Or upgrading a site with Version 1 to Version 3. Or upgrading a site with Version 2 to Version 3. Unfortunately, in this blog with screen shots, I couldn’t prove to you that it does work. I could just show previous screen shots and say it works. However the code is available to you on my OneDrive, with each version in separate folders so that you can load each one up in turn inside Visual Studio and publish and test out this yourself.