Add a Stylesheet to a Page from a Sharepoint 2010 Sandbox WebPart

I have a module in my project that deploys a style.css document to the site Style Library.  I wanted to add a reference to this Stylesheet from within my WebPart code to the page.  I never anticipated that this would be a problem, even in a sandbox solution and the restrictions that came with it.

I couldn't use the Microsoft.Sharepoint.WebControls.CssRegistration class becuase I was in a sandbox solution.  So I thought let's try using standard .Net methods, like adding to the Page.Headers collection, but in my sandbox WebPart that property was always null.

I couldn't find anyway of adding the Stylesheet reference server side from a WebPart in a sandbox environment.  The only option left was to use client side javascript to dynamically add the reference to the DOM.

Here is a snippet of code from my WebPart that accomplishes this:
protected override void RenderContents(HtmlTextWriter writer)
        {
            StringBuilder js = new StringBuilder();

            js.AppendLine("var added = false");
            js.AppendLine("for (i = 0; (a = document.getElementsByTagName(\"link\")[i]); i++)"); 
            js.AppendLine("{");
            js.AppendLine("  if (a.getAttribute(\"rel\").indexOf(\"style\") != -1");
            js.AppendLine("      && a.getAttribute(\"href\").indexOf(\"kwsresourcebooking365\") != -1)");
            js.AppendLine("  {");
            js.AppendLine("    added = true;");
            js.AppendLine("  }");
            js.AppendLine("}");
            js.AppendLine("if(!added)");
            js.AppendLine("{");
            js.AppendLine("  var head = document.getElementsByTagName(\"head\")[0];");  
            js.AppendLine("  if(document.createStyleSheet)");
            js.AppendLine("  {");
            js.AppendLine("    document.createStyleSheet('" + SPContext.Current.Site.Url + "/style%20library/folder/style.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.Url + "/style library/folder/style.css" + "';");
            js.AppendLine("    head.appendChild(css);");                        
            js.AppendLine("  }");
            js.AppendLine("}");
           
            base.RenderContents(writer);

            writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
            writer.RenderBeginTag(HtmlTextWriterTag.Script);
            writer.WriteLine(js.ToString());
            writer.RenderEndTag();
        }
The Javascript will first check to see if the Stylesheet link exists in the head. If it doesn't exist then it will check to see if the createStyleSheet method is available, which essentially means that we are in Internet Explorer or else manually create link tag. I did consider using the Sharepoint client script manager, but I think there maybe sandbox restrictions there too and I was growing tired of hitting sandbox brick walls. I hope this saves you some time and frustration!

6 comments:

stefan said...

Thx for this piece of code - safed my day .. it's not so easy to work with sandboxed solutions ;)

AJ said...

Excellent. I'm trying to turn a few web parts into Sandboxed solutions and this is exactly what I needed.

Ian Chivers said...

What's cool is you can also use this method to add jQuery to your Office365 sandbox solutions too.

David Wesst said...

This saved me and my team so much pain and suffering. Thank you for posting!

JoseLuis said...

Thanks Ian that works like a charm...!

Salman Siddiqui said...

Line 9 has a hard coded reference to the site home page itself?
"kwsresourcebooking365"