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.

Get the user claim token string in powershell from Windows domain/name


To grab the User Claim token equivalent of their Windows Domain/Name in powershell you just need to have the following Get-SPClaim function within your script.

Add-PSSnapin Microsoft.SharePoint.PowerShell
$m = [Microsoft.SharePoint.Administration.Claims.SPClaimProviderManager]::Local

Function Get-SPClaim{
param([string]$user)
$claim = New-SPClaimsPrincipal -identity $user -IdentityType "WindowsSamAccountName"
return $m.EncodeClaim($claim)
}

$UserClaim = Get-SPClaim("cannonfodder\administrator")
Write-Host $UserClaim

The above code will display the following on the screen.

i:0#.w|cannonfodder\administrator

The document could not be created. The required application may not be installed properly, or the template for this document library cannot be opened.


Working within my VM this morning, and just testing out basic functionality of SharePoint on my demo site. I went to do a very simple task of creating a new document. I received the following pop up.

It took me a moment, but I realised I didn’t have any Office products installed on my VM, however I did have Office Web Apps. I thought I should still be able to create a new document. It turns out that if you disable an Internet Add-On this message goes away. The Internet Add-On is called SharePoint OpenDocuments Class, (which sounds like it needs to be enabled for it to work!)

As soon as I disabled it, without any browser restart, I was able to create a new document.

SharePoint 2013 Calendar not displaying correctly with IE11


Been working on my SharePoint Dev machine where I needed to add a calendar to my site. Wrote the code, everything looked good. I then VPN onto the client’s machine to upload the code to their QA environment. Soon as I looked at the calendar, I notice that it was displaying funny and not working as expected. After ensuring I had indeed uploaded the latest code, I decided to go back to basics and create an out of the box site and add a calendar to the site. Again the calendar didn’t look right.

Non Working Calendar

I jumped on the web front end, and used IE11 from there and the same site appeared correctly.

From my machine I checked with Chrome, Safari, Firefox and all appear correctly, but for some reason my IE didn’t work. It was the first time I’ve had a case of “It doesn’t work on my machine” but does everywhere else.

I opened up the developer tools and took a look at what was being loaded on the page, and compared the two browsers. It appeared that on the working browser I had an additional JavaScript file loaded “SP.UI.ApplicationPages.Calendar.js”, perhaps this file applied a css. Needed to work out why this file wasn’t being loaded. Using the IE developer tools, I viewed the calendar.aspx file in both browsers and copied the source for comparisons. Not only did this highlight to me that at line 43 sp.ui.applicationpage.calendar.js wasn’t being referenced, but two line up, where it registers the browserScript, it was loading up a different javascript file. It seemed to think that I wasn’t using an IE browser. (Even though in Chrome, Firefox etc, it still loads the ie55up.js file!)

Non-working. (Loads non_ie.js)

Working (Loads ie55up.js and sp.ui.applicationpages.calendar.js files)

A colleague of mine suggested to use fiddler to look at the User Agent being sent in the request. (Thanks Chris) It turned out that two different User-Agent were being sent.

Non-working: (Mozilla/5.0 (Windows NT 6.3;WOW64;Trident/7.0;rv:11.0) like Gecko)

Working: (Mozilla/4.0 (compatible;MSIE 7.0;Windows NT 6.3;WOW64;Trident/7.0;.NET4.0E;.NET4.0C;.NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729)

I was able to prove that it was the User Agent causing the issue, by using IE developer tools, and changing the User agent string there. Which then made my calendar display correctly. I also tested the original User Agent string, and if I removed the like Gecko from the User Agent string, the calendar did display correctly. It appears it’s the “Like Gecko” that causes the problem.

This gave me enough information to try and find something on the internet that could help me with my problem. I came across Jeremy Sinclair blog, which implies there is an issue with IE11 and SharePoint 2013.

http://sinclairinat0r.com/2014/03/06/internet-explorer-11-compatibility-fixes-for-sharepoint-2013/

http://sinclairinat0r.com/2014/03/14/spoofing-ie10s-user-agent-in-iis-for-ie11-support-in-sharepoint-2013/

Jeremy explains in his blog that the following doesn’t work correctly in IE11 with SharePoint 2013, even with SharePoint 2013 SP1 the issues are still there.

  • Edit Page doesn’t place the page in Edit mode (especially on custom page layouts)
  • If you do happen to use a built-in page layout, any webparts added are unable to be customized.
  • The calendar view doesn’t look right
  • The calendar overlay button on the calendar view is disabled.

Jeremy second blog post above show you how to use a URL Rewrite Module for IIS, and configure IIS to re-write the HTTP_USER_AGENT.

So how comes it worked on the client QA SharePoint box browser, and worked on my browser pointing to my dev environment, but not when I used my browser to point to the client QA SharePoint Site?

I have learnt that in IE Internet Options, on the Security Tab, when a site is a Local Intranet site, it uses the working User Agent. So when I was trying to connect to my farm that was already set up as a Local intranet. When I was on the remote desktop of the web front end, again I was inside the client domain and the site was already configured to Local Intranet. The connection of my browser on my pc through the VPN to the client’s farm sent the request via Internet. As soon as I put the URL of the client’s site in my Local Intranet settings, the calendar then appeared correctly to me.

Hopefully a patch will eventually be released, and this won’t be an issue. Until it is, I hope this blog helps explains the problem to you and gave you the answer quicker than it took me to work out.

Visual Studio Web Essentials, Minified and Source Map files


Working in the SharePoint 2013 online world I have found myself deep in the world of JavaScript files. Now as a good developer I ensure that my JavaScript files are all minified before deploying to a production server. However what happens if there is a JavaScript error on the production server. You would normally see an error like below:

Line: 1, Column: 83008. Well yeah, that’s going to be easy to solve. To makes matters worse, if I look at the cannonfodder.min.js file, line 1 looks a bit like the following:

However you could hit “Turn Pretty On” button

IE11

Chrome – (Bottom left)

Which makes the above text looks like the following:

Not exactly the file I originally wrote, as functions and variables are still minified to single letters.

One solution that I used to use was have a custom action script link, that points a piece of JavaScript code, that either adds the minified or un-minified file to the page depending if there was “jsdebug” in the query string on the page.


var Cannonfodder = Cannonfodder || {};

Cannonfodder.LoadMainJs = (function () {

    var scriptElement = document.createElement('script');

    scriptElement.setAttribute('type', 'text/javascript');

    if (window.location.href.indexOf('jsdebug') != -1) {

        scriptElement.setAttribute('src', '/assets/scripts/cannonfodder.js ');

    } else {

        scriptElement.setAttribute('src', '/assets/scripts/cannonfodder.min.js ');

    }

    document.getElementsByTagName('head')[0].appendChild(scriptElement);

}());

There is nothing wrong with doing the above, the only issue is that you are inserting the javascript file into the page with a custom action. If you wanted just to add the JavaScript link to your masterpage, or HTML page etc you couldn’t use this method.

This is where minified and source map files come in handy.

 

Web Essentials for Visual Studio

Before I explain further about Minified and Source Map files, let me show you a Visual Studio plugin that will do most of the work for you. It’s called Web Essentials and can be downloaded from http://vswebessentials.com/. It is available for Visual Studio 2010, 2012 and 2013. It has many features, but the feature you are installing it for, is so that it automatically minifies and creates a map file for your JavaScript files.

How to minify

Once you have installed Web Essentials extension, and have a project with a group of JavaScript files, all you need to do is select the JavaScript files, and right click.

You will see that you have a new menu item “Web Essentials” and inside this menu item, you can Create JavaScript bundle file. By clicking this you are asked to name your bundle. Once you have named your bundle and click OK, it will create 4 files based on your bundle name.

The files:

[BundleName].js – is all the JavaScript files put together into one file, that isn’t minified. This is the easy to read version. (Although not used any further)

[BundleName].min.js – is all the JavaScript files put together into one file, but this file is minified.

[BundleName].min.js.map – is the source map file. This is a file that holds information about your original files. When you query a certai line and column number in your generated minified JavaScript you can do a lookup in the source map which returns the original location. A map file can look as simple as the following.


{

 "version" : 3,

"file": "Cannonfodder.min.js",

"mappings": "AAAAA,SAASA,kBAAmB,CAACC",

"sources": ["test.js"],

"names": ["window", "src", "maps", "are", "fun"]

}

 

[BundleName].js.bundle – This is an XML file, also the file that groups the other 3 files. This XML file contains the files that need to be minified, also it determines the order. The bundle file looks similar to the following:


<?xml version="1.0" encoding="utf-8"?>

<bundle minify="true" runOnBuild="true" output="Cannonfodder.js">

<!-- The order of the <file> elements determines the order of them when bundled. -->

<file>test.js</file>

<file>anotherfile.js</file>

<file>mycoreutilities.js</file>

</bundle>

 

What is really cool about using web essentials, is any changes you make to your original javascript files, as soon as you save it within Visual Studio, the 3 bundle files are recreated/updated. ([bundle].js, [bundle].min.js, [bundle].min.js.map)

 

What to deploy to the server

I’ve created a basic demo to explain what needs to be deployed to the server.

What I have is a module called assets. I added 3 JavaScript files to my assets module. Then, using Web Essentials created my Cannonfodder bundle from the 3 JavaScript files. Lastly I have created a Custom Action Script link which adds “~SiteCollection/Assets/Cannonfodder.min.js” to the page for simplicity. (Save worrying about creating a Master Page for this demo)

The files highlighted in yellow are the files, I’ve included in the Elements.xml file which will be uploaded to the server.

When I hit my page, the only file that I’ve told to load on the page is the minified file Cannonfodder.min.js.

 

Browsers and debugging the minified file

I have deployed my sandbox solution to the server, and using Chrome I can see my original files instead of the minified files. Here I will show you how this works.

By default Chrome doesn’t load the unminfied files, even when you enable the developer tools (F12) it doesn’t automatically load the unminified files. To get this to work you need to go into the settings of Chrome, by clicking on the cog on the top right of the developer toolbar.

You need to ensure “Enable JS source maps” is turned on. Now refresh the page. In the source panel, you will now see your original files and the minified files.

With “Enable JS Source maps” turned off, you will not get the original files in the source panel. (There are more files loaded here before I took my screenshot, compared to the last screenshot)

Ok, so I can see my original files, but how does that help me? Well now I can actually put a break point on my original code, which gets hit as my page runs.

This may seem like magic, but it is to do with the final line you will find in the min.js file.


/*

//# sourceMappingURL=Cannonfodder.min.js.map

*/

This line tells the browser to read the map file if found, it can then load the original files from the map file. The mappings in the map file, allows the browser to work out exactly where in the minified file you are in the original files. So for example, if you click “turn pretty on” for your minified file, and then attempt to put a break point in this file, the actual breakpoint it makes is in your original file. You can see this by the “Breakpoints window”.

 

Other Browsers

Firefox in the debug tools can view the original files. Apparently according to this Microsoft Article http://msdn.microsoft.com/en-us/library/dn255007(v=vs.85).aspx IE11 with Windows 8.1 update also can do this. However I cannot see the extra buttons that Microsoft States are there to perform what I did in Chrome.

What I have


What Microsoft says I should have


The last two buttons are Just My Code and Enable source maps. If anyone works out how to get these two buttons to appear, please place a message in the comments below.

Update: I have just installed the latest updates for my Windows 8 machine and can confirm that them buttons are now there. I obviously didn’t have 8.1 installed.

 

Issues I’ve discovered

The main issue I’ve had when debugging my files is that in the console window, if I wanted to see a variable value, I would normally just type the variable into the console and it would give me my value. However, because the browser is actually running your minified file, and showing you the original files, your variables are not actually your variables.

What do I mean? Well, below I have put a break point on my simple displayDateandName(name) function. This breakpoint is showing my original file.

When I try and get “date” variable, it states it’s undefined. With the “name” variable it displays nothing. This is because it is running your minified file, and you can tell this by looking at the Local Scope Variable window.

You can see variables called

n: “Paul”

t: Tue Apr 08 2014 21:59:40 GMT+0100 (GMT Daylight Time)

Which if you can find it within your minified file, you will see that what these variables have been minified too

Resources

http://msdn.microsoft.com/en-us/library/dn255007(v=vs.85).aspx – IE 11 and Map Files

https://developers.google.com/chrome-developer-tools/docs/javascript-debugging#source-maps – Chrome and Map Files.

http://www.codeproject.com/Articles/649271/How-to-Enable-Source-Maps-in-Firefox – Firefox and Map files

http://vswebessentials.com/ – Visual Studio Extension Web Essentials.

http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/ – HTML5Rocks Introduction to JavaScript Source Maps.