Why CSSRegistration Will Not Work in a SharePoint 2010 Sandbox Solution

This post is one post in a series of posts I penned in hopes it would help those looking to move a SharePoint 2010 Visual Studio 2010 farm based solution to a sandbox. There are many gotcha’s and pitfalls that you may run into or you may want to be aware of. You can learn more about this series here as well as download the CodePlex Project, From the Farm to the Sandbox, which includes the sample farm and sandbox solutions references through this series.
The related posts include:
Automatically Check In Files in a SharePoint 2010 Sandbox Feature Event Receiver
SharePoint 2010 Sandbox Feature Deactivation – Removing Module Assets
The Proper Web Part Control Class for a SharePoint 2010 Sandbox Solution
Custom Properties in a SharePoint 2010 Sandbox Web Part
Link to JavaScript Files in a SharePoint 2010 Sandbox Solution

CSSRegiration – Microsoft.SharePoint.WebControls.CssRegistration

A standard way to link a CSS Stylesheet to a page within a SharePoint 2010 web part would be to use the Microsoft.SharePoint.WebControls.CssRegistration method, i.e.:

1
2
3
4
Microsoft.SharePoint.WebControls.CssRegistration css = new CssRegistration();
css.After = "corev4.css";
css.Name = SPContext.Current.Site.RootWeb.URL +/Style Library/css/custom-stylesheet.css;
this.Controls.Add(css);

Well when you look up the Microsoft.SharePoint.WebControls.CssRegistration method we can see that this is not available in Sandboxed solutions, thus explaining why it doesn’t work when we port our Farm solution to the sandbox. This actually makes sense as a sandboxed web part does not have access to the “Page” element, but still, a shame. What can we do?
In your web part’s Render function, you could use some javascript to add a link to your css file to the head section of your page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
StringBuilder js = new StringBuilder();
js.AppendLine("var head = document.getElementsByTagName("head")[0];");
js.AppendLine("if(document.createStyleSheet)");
js.AppendLine("{");
js.AppendLine(" document.createStyleSheet('" + SPContext.Current.Site.RootWeb.URL + "/Style%20Library/css/custom-styles.css" + "');");
js.AppendLine("} else {");
js.AppendLine(" var css = document.createElement('link');");
js.AppendLine(" css.type = 'text/css';");
js.AppendLine(" css.rel = 'stylesheet';");
js.AppendLine(" css.href = '" + SPContext.Current.Site.RootWeb.URL + "/Style%20Library/css/custom-styles.css" + "';");
js.AppendLine(" head.appendChild(css);");
js.AppendLine("}");
writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
writer.RenderBeginTag(HtmlTextWriterTag.Script);
writer.WriteLine(js.ToString());
writer.RenderEndTag();

That is it, that is really all there is to it. What the rendered JavaScript code does is check to see if the browser supports document.createStyleSheet. If it does then it creates a new stylesheet link to your style sheet. If not then is creates a new link element to your stylesheet.
No more CSSRegistration needed. My primary complaint with this method is that if you have one web part that is used multiple times on one page then the stylesheet may be added multiple times. Not the best solution, but without more headaches in the js coding this would be tough to solve.
There is another method I recently found. You can add a CustomAction to your webpart’s Elements.xml file. I found that this is not very well documented, but it works. Normally CustomAction is used to add something to the ribbon, but we can use it to do anything, almost.

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<elements xmlns="http://schemas.microsoft.com/sharepoint/" >
  <module Name=”CusomWebPart" List="113" Url="_catalogs/wp">
    <file Path="CusomWebPartCusomWebPart.webpart" Url="CusomWebPart.webpart" Type="GhostableInLibrary">
      <property Name="Group" Value="Custom" />
    </file>
  </module>
  <customAction
   Location="ScriptLink"
   ScriptBlock="document.write('&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;~sitecollection/Style%20Library/CSS/custom-styles.css&quot; /&gt;');"
   Sequence="100" />
</elements>

Now what this does is first add your CustomWebPart to the web part library, but second, it adds a CustomAction, with a location of ScriptLink. The actual location of ScriptLink is not in the section, rather at the top of your . This will make sure that your stylesheet is only included once no matter how many times your custom web part is added to a page. You will want to be aware that Custom Action ScriptLinks are added to every page, meaning that your css file will be loaded on every page in this site collection. Not ideal for performance, but I find it is better than adding the css directly in the code. You could also add a particular class or block of code to your web part that you could use javascript within the ScriptBlock to look for. If that block of code is found at least once, i.e. your web part has been added to a given page, then fire the code to load the additional css file.
For a complete review of the Farm and Sandbox solutions’ Feature Event Receiver, please reference From the Farm to the Sandbox for the full code. Also, please do not forget to check out the other posts in this series, all related to converting a farm solution to a sandbox solution.

Leave a Comment

Your email address will not be published. Required fields are marked *

Enter Code *

Filed Under

Related

Are you preparing to launch a new #SharePoint intranet?

Don’t spring it on employees out of the blue. First, talk to as many of them as you can.

Planning is just phase one. For all of our tips, watch our recent webinar!

http://ow.ly/dsQM50GqPI5

It's that time again! Join #Microsoft MVP & Regional Director, @EricOverfield on Thursday, October 28th, at 11:00 AM PST as he walks through #MicrosoftViva’s current state & offerings and what they mean to your #digitalworkspace right now.

http://ow.ly/3QFK50Gnx9f

It's the final countdown! Join @EricOverfield at 11am PST to learn about common pitfalls and paths to success when moving to #SharePointOnline. You'll walk away with practical tips to use in your organization today!

http://ow.ly/fdf150GjyJT

In today's episode of the #PixelMillWebinars, you'll learn from the experience of a global organization’s path to digital teamwork victory and get to see first-hand how to successfully plan a smooth migration for your team.

Join us at 11am PST!

https://pixelmill.com/webinar-9-takeaways-from-a-global-organizations-migration-to-sharepoint-online/

It's the day of the show y'all! Join #Microsoft RD +MVP @EricOverfield at 11am PST as we walk you through a multi-national enterprise software company’s migration journey to #SharePointOnline. Learn about common pitfalls and paths to success.

http://ow.ly/cN9250GjtGk

Subscribe to PixelMill's
E-news

* indicates required

Let's Talk Digital
Workspaces Today

Get In Touch