Wednesday, 25 February 2015

SharePoint 2013: How do I reference a html 'source' file from another site collection in a Content Editor Web Part?

Content Editor Web Parts are fantastic for rendering content, but there is small problem if you want to reference a file (through a ContentLink) on another site collection - you are not allowed to! Cross-site scripting is not a good thing.

This problem becomes apparent when you have a 'source' site collection that will host all the html/js files and you want all other site collections to reference this (single) source of truth.

There are a few options available to resolve the problem.
1. Copy all the JS/Html files to each site collection and reference them locally. (Easy, but it will create a maintenance nightmare if you have lots of site collections).
2. Enable Anonymous access to the 'source' site collection. (Easy, but not a great solution)
3. Install Content Link Web Part from Codeplex. (Better, but requires a Farm Solution)
4. Move the link from the ContentLink to the Content in the webpart.
The key to resolving the problem is nested CDATA tags.

In my project, we were using AngularJS, so used ng-include to point to my source file.

Here is my sample from the elements.xml for my page Module:

<AllUsersWebPart WebPartOrder="0" WebPartZoneID="RowLeft">
<![CDATA[
<WebPart xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/WebPart/v2">
  <Title />
  <FrameType>None</FrameType>
  <Description></Description>
  <IsIncluded>true</IsIncluded>
  <ZoneID>RightRow</ZoneID>
  <PartOrder>0</PartOrder>
  <FrameState>Normal</FrameState>
  <Height />
  <Width />
  <AllowRemove>false</AllowRemove>
  <AllowZoneChange>false</AllowZoneChange>
  <AllowMinimize>false</AllowMinimize>
  <AllowConnect>false</AllowConnect>
  <AllowEdit>false</AllowEdit>
  <AllowHide>false</AllowHide>
  <IsVisible>true</IsVisible>
  <DetailLink />
  <HelpLink />
  <HelpMode>Modeless</HelpMode>
  <Dir>Default</Dir>
  <PartImageSmall />
  <MissingAssembly>Cannot import this Web Part.</MissingAssembly>
  <PartImageLarge>/_layouts/15/images/mscontl.gif</PartImageLarge>
  <IsIncludedFilter />
  <Assembly>Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
  <TypeName>Microsoft.SharePoint.WebPartPages.ContentEditorWebPart</TypeName>
  <ContentLink xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor" />
  <Content xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor"><![CDATA[
<div id="description" ng-include="src='/Style Library/html/MyModule.html'" ></div>
  ]]]]><![CDATA[>
  </Content>
  <PartStorage xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor" />
</WebPart>
]]>
</AllUsersWebPart>

The key with nested CDATA is to close the root tags immediately once the nested tags are used and create a new CDATA tag immediately afterwards.


No comments:

Post a Comment