Participating in the Page Rendering Pipeline in SharePoint 2010 Sandbox Solutions – SPUserCodeWebPart

If you have been reading this blog of late, you probably picked up on the fact that I am a bit disappointed by the limitations of sandboxed solutions. I recently updated my original post on the subject to include the following:

<This is mostly wrong>

Issue #4 – Almost No Server Side Rendering – Forget About Using ASP.NET

I thought I would try to work around my ribbon issue with a simple custom WebControl. Turns out that, since the sandbox assembly is installed in ProgramDataMicrosoftSharePointUCCache, the regular worker process (w3wp.exe) that renders pages can’t load the custom UI assembly because it has no knowledge of the UCCache location. The same applies to code behind assemblies for ASPX.

You can create WebParts (sorta/kinda) but they are also extremely crippled. See http://blah.winsmarts.com/2009-12-You_can_deploy_WebParts_as_Sandboxed_solutions__but.aspx

</This is mostly wrong >

Well, I got to thinking… ‘I know that you can create sandbox solutions that include Web Parts, and SharePoint is loading them somehow. Maybe there is a way to get my controls onto the page!’

Turns out there is!!! I give you SPUserCodeWebPart. This little guy can load your assembly and its controls from the user code store.

<WebPartPages:SPUserCodeWebPart
runat="server"
Description="My WebPart" Title="Howdy y'all"
AssemblyFullName="MySandbox, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9120be3acbd2f74f"

SolutionId="YourSolutionIDHere"
TypeFullName="MySandbox.Howdy">
</WebPartPages:SPUserCodeWebPart>

Bear in mind that Web Parts are just user controls and you can use them even when the page is not a Web Part page. That means you can use them on regular ASPX pages and on master pages. This means that you can access controls and handle events on the page that contains this hook – as long as the controls are also contained in your Web Part. It seems that the way this works is that SharePoint generates a page within a page using the SPUserCodePage and SPUserCodeForm classes. The pattern I will be trying will be an ASPX page with a single SPUserCodeWebPart that wraps the control that implements the page logic. If I need to get at the outer shell I’ll emit JavaScript to do so.

 

Author: Doug Ware

A Reply to Sahil Malik’s Defense of the Sandbox Architecture

Sahil Malik has a response to my SharePoint 2010 Sandbox Solutions are Bad post that you can read here: Sandbox solutions are pretty damn good.
He also links to a Facebook conversation wherein Razi Bin Rai asserts "At heart of the argument of ‘SB solutions are bad’, there is actually more of a resistance against new way of doing things" and Sahil replies "True True Razi".

Not true at all. (I am always amazed when an Internet commenter thinks they know the mind of another from a tweet or a page of text).

There is in fact not a resistance against a new way of doing things. I came to this new technology with a great deal of excitement, but I find it distinctly lacking in its merits.

With regards to Sahil’s post – I believe that proxies are a sound and vital architectural choice. But they are not part of the sandbox even though SharePoint provides the means to invoke a specific type of proxy from the sandbox. In SharePoint they are, in fact, full trust components that require administrative access to install. My guess is that those who have permission to use them will do so if they are using Silverlight or heavy javascript with the new client namespace. Furthermore, they will use some form of server side proxies regardless of whatever deployment (sandbox or farm) choices they make.

And why not? By going with a predominately client side technology you don’t lose anything from the sandbox that you would have without it. Assuming you have admin access you can solve both issues #2 and #3 mentioned in my original post . But let us be completely honest about what this means; you solve them by having components outside the sandbox. Most, I think, would choose this architecture (proxies to server side services) when the UI is client side JavaScript or Silverlight with or without the sandbox. If we both agree that this is a sound architecture in and of itself, let’s not confuse the subject of the merits of the sandbox as it is implemented by talking about something that is clearly separate even though complimentary.

Besides, I don’t think full trust proxies will be an option on SharePoint Online or other hosted offerings anyway.

Sahil seems to be conflating my choice of the word ‘Bad’ with ‘useless’. This is not a useless technology, but it is a bad one. As you may know, I’ve been slowly making Elumenotion into an ISV. I hope to have some success with SharePoint Online and its analogs and so we are working on a variety of workarounds and trying to come up with a serviceable architecture. The fact is: there are workarounds and you can build solutions.

This concession made, let me reiterate what I think was the most important part of the original post. If you are going to do development on 2010 and you have access to the server your default choice should be farm solutions unless you have a compelling requirement to do otherwise – the pronouncements at PDC and elsewhere to the contrary (sandbox should be your default choice) are nonsense. Absent a clear requirement (like the need to run as a hosted solution) going with a sandbox will result is more code with strange workarounds and potentially less secure data for more money and time. If that’s not bad, then what is it?

I must admit that I was a little irked that I took the time to come up with three specific examples that Sahil ignored and substituted with a straw man when he wrote his rebuttal. I think I have addressed the full trust proxy point, but let me tackle a couple of his other points so that he need not be irked with me. 😉

First Sahil says ‘Farm solutions and custom code is the number one necessary evil on SharePoint projects. It is also the number one issue that causes problems and updates. And it is also the number one issue that causes contention between IT Pros and developers.’ To this I can only say ‘[citation needed]‘. It’s a huge assertion to make that does not jibe with my experiences or anecdotes from my peers or clients.

Second is that the sandbox provides a degree of monitoring that can prevent rogue apps from killing the server. I agree that this is a great thing especially if you are providing hosted services like SharePoint Online that preclude normal QA and monitoring processes for deployed code. Once again though, if you have the option of traditional development because you own the servers, traditional QA and WMI instrumentation along with ULS logging are a first line defense which should minimize the need for such a system.

Third Sahil says: ‘My feeling is that there’s been plenty of thought given to where and how those walls have been drawn.‘ My feeling is that insufficient thought and resources went into making these decisions. At some point they have to ship it and they decided where to put the resources. This stuff smacks of a version 1.0, let’s get it out the door deal. I am spending a lot of time in Reflector these days looking at the SharePoint assemblies. If there is a security or performance issue that caused them to deny access to the entire SharePoint.WebControls namespace I do not see it. The code for most of these controls is simple and straightforward. However, there are hundreds of them. My purely speculative guess is that they only had so much manpower to go around and they took the easy way out by blocking them all instead of looking at them individually.

Author: Doug Ware

Fixed Width Master Pages in SharePoint 2010

Note: This post is about the beta and is out of date. See this post, SharePoint 2010 Fixed Width Master Pages Revisited, for an approach that works better with the release version.

Edit: Since I wrote this post I found this one which has a solution I like better: http://styledpoint.com/blog/fixed-width-centered-sharepoint-2010-site/. I also recommend you take a look at Randy Drisgill’s starter master pages which you can read about here: http://blog.drisgill.com/2009/11/starter-master-pages-for-sharepoint.html.

I spent the last couple of hours attempting to make a fixed width master page for a 2010 project we’re working on. Everything was great except for the fact that I couldn’t get the scroll bars for the page to display! So, I started over testing as I went and the scrollbars disappeared as soon as I removed a certain <div>.

<div id="s4-workspace">

However, as soon as I added the div back, the scrollbars appeared, but my nice 960 px layout aligned to the left instead of centering. I looked at the CSS for this element, but saw nothing that should have the effect I was seeing and certainly nothing that should have made the scrollbars appear and disappear. After spending too much time fooling around with the CSS it occurred to me to look at the javascript. I used grep on the 14 hive looking for s4-workspace and it found a match in init.js.

Now init.js like the rest of the *.js files is minified, so I used this website – http://javascript.about.com/library/blformat.htm – to reformat the script to make it readable. A quick examination showed that I needed to add another class to the div as so (the final page will not have the inline style attribute but will instead use an additional class name):

<div id="s4-workspace" class="s4-nosetwidth" style=" margin-left: auto; margin-right: auto; width: 970px; background: url(/SiteAssets/PageBackground.png) no-repeat white;">

I had to make the div a little wider than what I wanted to avoid a horizontal scrollbar. I’ll figure that minor issue out later.

Author: Doug Ware

Code to Hide the Ribbon and Site Actions Menu for Anonymous Users

In Beta 2, SharePoint 2010 sites that use the publishing infrastructure have an option on the Navigation Settings page to hide the ribbon by default.

Other sites lack this functionality as does SharePoint Foundation. However, the code to do the hiding is simple:

public void HideRibbonForAnon()
{
  SPRibbon current = SPRibbon.GetCurrent(this.Page);

  if (current != null && !this.Page.Request.IsAuthenticated)
  {
    current.CommandUIVisible = false;

    SiteActions actions = SiteActions.GetCurrent(this.Page);

    if (actions != null)
    {
       actions.Visible = false;
    }
    HideStatusBar();
  }
}
internal void HideStatusBar()
{

   string script = 
      "document.onreadystatechange=fnRemoveAllStatus; function fnRemoveAllStatus(){removeAllStatus(true)};";
   this.Page.ClientScript.RegisterClientScriptBlock(typeof(HideTheRibbon), "statusBarRemover", script, true);
}

 

Author: Doug Ware

SharePoint 2010 Sandbox Solutions are Bad

Update: There is a way to load controls and insert code into the page rendering pipeline!

Update below: See #4. Basically, you can forget about using 99% of everything you know about ASP.NET if you want to sandbox.

I wish I could tell you that this was one of those posts where the title is a trick. It isn’t and there will be no ‘but in spite of all that it’s really great’ moral to this post. After spending a couple of weeks digging deeply into this architecture and its merits I am left profoundly disappointed by the reality of what is present in Beta 2. I hope that my position on this will change as we get closer to release and I also hope that if what follows is wrong the Internet will set me straight.

Most of my disappointment comes from the height of the walls around the sandbox and what I believe will be the result when this stuff hits the real world.

Issue #1 – No Access to SharePoint.WebControls Namespace

This one is really hard to understand – you can’t create a Web Part that uses any of the built in controls which you can use in SharePoint Designer! For example, I have a Web Part which I will talk about in a later post that hides the ribbon and the site actions menu if the user is not authenticated. The version I have won’t work as a sandbox solution because you can’t use the SPRibbon class in a sandboxed solution. So the sandbox solution has almost no control over the server side rendering of pages that contain sandboxed controls and much worse, prevent you from building pages that contain any of the built in SharePoint controls.

Issue #2 – No Elevation of Privileges = Less Security | More Complexity

In other words, sandboxed code can’t do anything that the current user can’t do. On the surface this seems reasonable. However, what if you want to collect data from a user and store the result somewhere that the user is unable to access? What if you want to display a subset of information to a user on a page but prevent access to the underlying data? Both are common requirements, but you can’t do it with a sandbox solution because your code is always under the user’s context. I predict that many people will take the easy way out and simply leave the lists that contain the data open to everyone. I also predict that many people will try to work around this restriction and create complex solutions that actually increase the attack surface.

Issue #3 – No Ability to Send Email

One of the methods that is explicitly blocked in the sandbox is SPUtility.SendEmail. As far as I know, there is no alternate method provided in SharePoint. However, you can use the ASP.NET email classes. The catch is that you can’t read information about the farm’s SMTP server so you have to create workarounds.

<Update> See this post: Participating in the Page Rendering Pipeline in SharePoint 2010 Sandbox Solutions – SPUserCodeWebPart for a way around this!

Issue #4 – Almost No Server Side Rendering – Forget About Using ASP.NET

I thought I would try to work around my ribbon issue with a simple custom WebControl. Turns out that, since the sandbox assembly is installed in ProgramDataMicrosoftSharePointUCCache, the regular worker process (w3wp.exe) that renders pages can’t load the custom UI assembly because it has no knowledge of the UCCache location. The same applies to code behind assemblies for ASPX.

You can create WebParts (sorta/kinda) but they are also extremely crippled. See http://blah.winsmarts.com/2009-12-You_can_deploy_WebParts_as_Sandboxed_solutions__but.aspx

</Update>

Conclusion

There’s more, but those are my main issues. My belief is that sandbox solutions as they stand today are a dead on arrival technology – at least where the server side object model is concerned for controlling the UI.

I think that they will be popular as a deployment model for applications that use the SharePoint.Client namespace with javascript and Silverlight. I can certainly hide the ribbon with javascript on the client – but I shouldn’t have to. I remain concerned that there is no good answer to #2 with regards to client side code. It would be nice if SharePoint allowed some sort of trusted caller infrastructure that allowed elevation to site owner. This should be possible at least with Silverlight.

However, you should not be fooled by the pronouncements that sandbox should be your default choice as was declared at PDC. If you are doing traditional development on a farm you own, the only thing you will get by going sandboxed is irritation from the sand.

Author: Doug Ware