2010-12-10

ViewState problems with Sandbox Web Parts in SharePoint 2010

I have been playing around with developing sandbox web parts for SharePoint 2010 Foundation. With one particular web part, i had a form that was pretty large, over 300 fields. Initially i had no problems with the form loading and submitting. Gradually i started to convert some of the fields to dropdownlists, and databinding not insignificant datasets. At some point the form started to still display, but would not submit. I kept getting the generic error.

Web Part Error: Unhandled exception was thrown by the sandboxed code wrapper's Execute method in the partial trust app domain: An unexpected error has occurred.

My first attempt to solve this, was to locate the error. I try/catched all of the UI events. Strangely the exception was not being caught. Odd. Next i tried disabling sections of logic in web part and found that if i disabled the databind logic, i got no error. I figured it must have been one of the datasets causing an issue (but really that was a wrong assumption now that i know the true cause). So I continued on. I had to spend a while finding which dropdown sets were causing the problem, but i did narrow it down to one dataset, which also happened to be the largest. Hmm the largest, i had a feeling it might have something to do with a httppost max size at this point. So i reduced the dataset to only 50 records. Sure enough the error went away. With a few tests and page view sources, i found that the error would happen when the form size went over 128KB no matter what dataset had the largest amount of records.

I then decided to look at the ULS logs (which i probably should have done first) and had this error trace


SPUCWorkerProcess.exe (0x165C) 0x1744 SharePoint Foundation Sandboxed Code Service fe8s Medium - - Unhandled exception was thrown by the sandboxed code wrapper's Execute method in the partial trust app domain: An unexpected error has occurred. - userCodeWrapperType = "Microsoft.SharePoint.UserCode.SPUserCodeWebPartWrapper", userAssemblyGroupId = "E8C0D7A9294B4BCCB63757BF4AB4BC47-UCftMMyPOXDR6ibqgsTcXIE7gh71nqlnnuite7AdBB8=", siteCollectionId = "c02189c4-1dea-4969-b2b8-8240dfe4ef65" - Inner Exception: Microsoft.SharePoint.UserCode.SPUserCodeSolutionProxiedException: Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> Microsoft.SharePoint.UserCode.SPUserCodeSolutionProxiedException: Value cannot be null. Parameter name: path1 at System.IO.Path.Combine(String path1, String path2) at System.Web.HttpRawUploadedContent.TempFile..ctor() at System.Web.HttpR...
SPUCWorkerProcess.exe (0x165C) 0x1744 SharePoint Foundation Sandboxed Code Service fe8s Medium ...awUploadedContent.AddBytes(Byte[] data, Int32 offset, Int32 length) at System.Web.HttpRequest.GetEntireRawContent() at System.Web.HttpRequest.FillInFormCollection() at System.Web.HttpRequest.get_Form() at System.Web.HttpRequest.get_HasForm() at System.Web.UI.Page.GetCollectionBasedOnMethod(Boolean dontReturnNull) at System.Web.UI.Page.DeterminePostBackMode() at Microsoft.SharePoint.UserCode.SPUserCodePage.DeterminePostBackMode() at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) --- End of inner exception stack trace --- Server stack trace: at System.Web.UI.Page.HandleError(Exception e) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean inc...
SPUCWorkerProcess.exe (0x165C) 0x1744 SharePoint Foundation Sandboxed Code Service fe8s Medium ...ludeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest() at System.Web.UI.Page.ProcessRequest(HttpContext context) at Microsoft.SharePoint.UserCode.SPUserCodeWebPartWrapper.ExecuteHttpRequest(SPUserCodeWebPartHttpRequestContext webPartExecutionContext, SPUserCodeWebPartHttpResponse httpRequestResponse) at Microsoft.SharePoint.UserCode.SPUserCodeWebPartWrapper.Execute(SPUserCodeExecutionContext executionContext) at Microsoft.SharePoint.UserCode.SPUserCodeApplicationHostAppDomainRef.ExecuteWrapper(SPUserCodeWrapper wrapper, SPUserCodeExecutionContext executionContext) at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage...
SPUCWorkerProcess.exe (0x165C) 0x1744 SharePoint Foundation Sandboxed Code Service fe8s Medium ...(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs) at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.EndInvokeHelper(Message reqMsg, Boolean bProxyCase) at System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(Object NotUsed, MessageData& msgData) at Microsoft.SharePoint.UserCode.SPUserCodeApplicationHostAppDomainRef.CodeToExecuteWrapper.EndInvoke(IAsyncResult result) at Microsoft.SharePoint.UserCode.SPUserCodeApplicationHostAppDomainRef.Execute(Type userCodeWrapperType, SPUserCodeCachedAssemblyGroup userAssemblyGroup, Guid siteCollectionId, Byte[] binaryUserCodeToken, Byte[] proxyO...
SPUCWorkerProcess.exe (0x165C) 0x1744 SharePoint Foundation Sandboxed Code Service fe8s Medium ...perationToken, SPUserCodeExecutionContext executionContext)
SPUCHostService.exe (0x12E4) 0x14CC SharePoint Foundation Sandboxed Code Service fe3r Medium - - Unhandled exception was thrown by the sandboxed code wrapper's Execute method in the partial trust app domain: An unexpected error has occurred. - Monitored process "ipc://f28fa0e5-d648-4c74-a67f-4ae8dc6f1856:7000" has encountered an unhandled exception while executing user code. - Inner Exception: Microsoft.SharePoint.UserCode.SPUserCodeSolutionProxiedException: Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> Microsoft.SharePoint.UserCode.SPUserCodeSolutionProxiedException: Value cannot be null. Parameter name: path1 at System.IO.Path.Combine(String path1, String path2) at System.Web.HttpRawUploadedContent.TempFile..ctor() at System.Web.HttpRawUploadedContent.AddBytes(Byte[] data, Int32 offset, Int32 length) at System.Web.HttpRequest.GetEntire...
SPUCHostService.exe (0x12E4) 0x14CC SharePoint Foundation Sandboxed Code Service fe3r Medium ...RawContent() at System.Web.HttpRequest.FillInFormCollection() at System.Web.HttpRequest.get_Form() at System.Web.HttpRequest.get_HasForm() at System.Web.UI.Page.GetCollectionBasedOnMethod(Boolean dontReturnNull) at System.Web.UI.Page.DeterminePostBackMode() at Microsoft.SharePoint.UserCode.SPUserCodePage.DeterminePostBackMode() at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) --- End of inner exception stack trace --- Server stack trace: at System.Web.UI.Page.HandleError(Exception e) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, ...
SPUCHostService.exe (0x12E4) 0x14CC SharePoint Foundation Sandboxed Code Service fe3r Medium ...Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest() at System.Web.UI.Page.ProcessRequest(HttpContext context) at Microsoft.SharePoint.UserCode.SPUserCodeWebPartWrapper.ExecuteHttpRequest(SPUserCodeWebPartHttpRequestContext webPartExecutionContext, SPUserCodeWebPartHttpResponse httpRequestResponse) at Microsoft.SharePoint.UserCode.SPUserCodeWebPartWrapper.Execute(SPUserCodeExecutionContext executionContext) at Microsoft.SharePoint.UserCode.SPUserCodeApplicationHostAppDomainRef.ExecuteWrapper(SPUserCodeWrapper wrapper, SPUserCodeExecutionContext executionContext) at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs) ...
SPUCHostService.exe (0x12E4) 0x14CC SharePoint Foundation Sandboxed Code Service fe3r Medium ... at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.EndInvokeHelper(Message reqMsg, Boolean bProxyCase) at System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(Object NotUsed, MessageData& msgData) at Microsoft.SharePoint.UserCode.SPUserCodeApplicationHostAppDomainRef.CodeToExecuteWrapper.EndInvoke(IAsyncResult result) at Microsoft.SharePoint.UserCode.SPUserCodeApplicationHostAppDomainRef.Execute(Type userCodeWrapperType, SPUserCodeCachedAssemblyGroup userAssemblyGroup, Guid siteCollectionId, Byte[] binaryUserCodeToken, Byte[] proxyOperationToken, SPUserCodeExecutionContext executionContext)


The key text being

Value cannot be null.
Parameter name: path1
at System.IO.Path.Combine(String path1, String path2)
at System.Web.HttpRawUploadedContent.TempFile..ctor()

I have seen something like this before, when trying to use file uploads in a sandbox web part. Basically the HTTP object in the SPUCWorkerProcess is not fully functional. You can see how the process works from here http://msdn.microsoft.com/en-us/library/ff798382.aspx. So what was this error telling me, and how did it relate to the 128KB limit i was seeing? I had a guess that at this limit, the http object stopped buffering the request in memory and started writing it to a temporary file on disk. Took a few google searchs to find the appropriate key to set to increase this limit http://msdn.microsoft.com/en-us/library/system.web.configuration.httpruntimesection.requestlengthdiskthreshold.aspx. I set this on the sharepoint vss web.config. But this didnt fix the problem.

Both of the sandbox processes are well ... processes. SPUCHostService.exe/SPUCHostService.exe. I doubted that they would have httpRuntime settings i could change. But i went to the folder to see. Inside the folder i found an extra web.config (C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\UserCode\web.config), maybe i could use that. I added and tried again. To my surprise it fixed the problem.

Well it fixed the problem for my local machine, too bad that solution would not work on a hosting provider. There would be little chance they would change their UserCode settings for me. My next question was, why was so much data being sent the to sandbox process in the first place. Remember this only happens when the form is submitted. I took a guess that it was related to the viewstate, so tried disabling that, and bingo the problem went away. It does mean though that i'm going to have to manually deal with the postback binds, but at least the form is not crashing now.

2010-11-19

SharePoint Client Model from Powershell

I have seen a few people attempt to use the client access model from powershell, but they have mostly failed. The reason being, powershell does not allow extension methods. You can get most of the way, but when you try to call Load() or ExecuteQuery() it fails. I really like being able to do things in powershell scripts, as they are super easy to edit/change when you need. Surely i could get the client model to work from scripts.

I knew that powershell allows you compile and execute c# inline, hopefully i could use that feature. It was pretty easy to throw together a test, as it was just c# i was using.

The next problem i encountered; was powershell not loading the client access assemblies. No matter what i tried, i could only get powershell to load them IF the dlls were in the same directory as the powershell executable. Well for me that is not an ideal solution, i like to be able to copy a directory somewhere, and it just works.

What i found was a way you can override the powershell assembly loading
http://stackoverflow.com/questions/2664028/how-can-i-get-powershell-added-types-to-use-added-types

Then it was just a matter of intergrating it with the rest of the script.

Add-Type -Language CSharpVersion3 -TypeDefinition @' 
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
namespace Internal.Powershell {
public static class AssemblyResolver {
private static Dictionary<string, string> _assemblies = new Dictionary<string,string>(StringComparer.CurrentCultureIgnoreCase);
static AssemblyResolver() {
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(delegate(object sender, ResolveEventArgs args) {
var assemblyName = new AssemblyName(args.Name);
if (_assemblies.ContainsKey(assemblyName.Name)) {
return Assembly.LoadFrom(_assemblies[assemblyName.Name]);
}
return null;
});
}
public static void AddAssemblyLocation(string path) {
_assemblies.Add(Path.GetFileNameWithoutExtension(path), path);
}
}
}
'@
[Internal.Powershell.AssemblyResolver]::AddAssemblyLocation("..\..\lib\Microsoft.SharePoint.Client.Runtime.dll")
[Internal.Powershell.AssemblyResolver]::AddAssemblyLocation("..\..\lib\Microsoft.SharePoint.Client.dll")

$ReferencedAssemblies = @(
"Microsoft.SharePoint.Client.Runtime",
"Microsoft.SharePoint.Client"
)
$TypeDefinition = @"
using System;
using System.Collections.Generic;
using System.Net;
using System.Linq;
using System.IO;
using System.Text;
using Microsoft.SharePoint.Client;
namespace Internal.Powershell {
public static class SharePointClient {
public static void Main() {
using (ClientContext client = new ClientContext("http://url")) {
client.AuthenticationMode = ClientAuthenticationMode.Default;
client.Credentials = new NetworkCredential("username", "password", "domain");
var web = client.Web;
client.Load(web,
item => item.Title,
item => item.Description);
client.ExecuteQuery();
Console.WriteLine(web.Title);
Console.WriteLine(web.Description);
}
}
}
}
"@
Add-Type -ReferencedAssemblies $ReferencedAssemblies -TypeDefinition $TypeDefinition -Language CSharpVersion3
[Internal.Powershell.SharePointClient]::Main()

2010-11-18

SharePoint 2010 Team Site All Features

I needed to duplicate a Team Site definition, including all the feature staplings, posting it here in case anyone needs it

Team Site (STS#0) Features

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\SiteTemplates\sts\xml\ONET.XML

BasicWebParts
Three-state Workflow Feature
TeamCollab
MobilityRedirect
WikiPageHomePage

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\FEATURES\BaseSiteStapling\basesitestapling.xml

BaseSite
-LocalSiteDirectoryControl
-PortalsLayouts
-WebPartAdderGroups
ReceiverAssembly="Microsoft.SharePoint.Portal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
ReceiverClass="Microsoft.SharePoint.Portal.SPSWebPartAdderFeatureReceiver"
-DocumentRoutingResources
-RecordResources
BaseWeb
-RelatedLinksScopeSettingsLink
-SlideLibrary
AssetLibrary
EnchancedTheming
Reporting
LocationBasedPolicy
MetaDataNav
Rating

Page.ParseControl with SharePoint Sandbox

There are many posts explaining that you cannot use visual web parts with the sharepoint sandbox. So this means you have to build your controls by hand, which is not that fun. Thinking I was smart, I tried to use the Page.LoadControl method to parse a string of controls. This way i could author the html easily.

Turns out though, that doesn't work. You get this error message in your webpart.






System.ArguementNullException: Value cannot be null. Parameter name: virtualPath at System.Web.VirtualPath.Create()

Which basically means that the process that executes the sandbox code is not a full ASP.NET pipeline, or doesn't have all the context/access object it needs. This is probably as security feature too.

Oh well, back to coding the control tree by hand.

Package SharePoint Project without SharePoint

For my current project, i was required to develop a sandbox web part. Normally i would just develop it in visual studio in my sharepoint vm. Working in the sharepoint vm though is not that fun, it can't use your local computer's full resources. Visual studio seems to lag when IIS takes all the memory.

The process I was using was:
1. Compile in VS
2. Package in VS
3. De-activate in Browser
4. Upload in Browser
5. Activate in Browser
6. Test in Browser

It would work a whole lot better if I could do that locally. If it was possible. With MOSS 2007 you could not open the sharepoint project on a machine without sharepoint, basically because vseex would not install. But now you can, as you can deploy the sharepoint components to a machine that does not have sharepoint installed.

When i tried to package initially though, it failed with a generic package failed error

By chance i figured out that if you delete the csproject.user file, visual studio 2010 will package the sharepoint wsp. When you dont have a csproject.user opening the project will show this error, which is what you want.








The Site URL property of the project has not been set. In the Properties window, enter the URL for the local SharePoint server.

2010-11-07

SharePoint Designer Custom Action in Dialog

SharePoint designer has a great way to create custom actions. There are many help posts out there on how to do that.
http://blog.furuknap.net/adding-custom-actions-in-sharepoint-designer-2010
You have three options to select "Navigate to form", "Initiate workflow" and "Navigate to URL"
The trouble with these actions and options (well the ones on the View Ribbon) is that they do not open in the dialog box

There a heaps more posts on creating custom actions that open in dialogs
http://www.chakkaradeep.com/post/Using-the-SharePoint-2010-Modal-Dialog.aspx
http://www.vinodunny.com/blog/post/Application-Page-Ribbon-Dialogs-on-SharePoint-2010.aspx
http://jomit.blogspot.com/2009/12/dialog-platform-in-sharepoint-2010-how.html

The problem with those though, is that the action must be defined before hand.
I really like how sharepoint designer allows you to configure the url on the fly.
There must be a way to combine the two ways.

I was hoping that the "Navigate to URL" option would be a href.
So i tried a simple javascript:alert("hi") for an action.
Sure enough i got an alert box.
From there it was just a matter of figuring out the showModalDialog command, and putting it on one line.

This action is great to use with the StartWorkflow component http://spc3.codeplex.com/

For View Ribbon actions
javascript:SP.UI.ModalDialog.showModalDialog({url:"{SiteUrl}/_layouts/Com.CodePlex.SPC3/StartWorkflow.aspx?List={ListId}&ItemID={SelectedItemId}&Workflow=WorkflowName",dialogReturnValueCallback: function(dialogResult, returnValue) { SP.UI.ModalDialog.RefreshPage(SP.UI.DialogResult.OK) }})

And for Display Form Ribbon actions
{SiteUrl}/_layouts/Com.CodePlex.SPC3/StartWorkflow.aspx?List={ListId}&ItemID={ItemId}&Workflow=WorkflowName

2010-10-27

DateTime filter in SharePoint 2010 List View

The way i got around this, was to pipe the result from the DateTimeControl to a HiddenField using inline code.

Added these controls
< SharePoint:DateTimeControl runat="server" id="FilterFrom" DateOnly="True" LocaleId="3081" SelectedDate="2010-10-01"/>
< asp:HiddenField runat="server" id="FilterFromFixed" />

Had this query
< Where>
< Geq>
< FieldRef Name="FirstDay"/>
< Value Type="DateTime">{FilterFromFixed}< /Value>
< /Geq>
< /Where>

Added this to web.config
< PageParserPath VirtualPath="/Lists/YourList/YourView.aspx" CompilationMode="Always" AllowServerSideScript="true" />

Then had this inline code in the view
< script runat="server">
protected void Page_Load(object sender, EventArgs e) {
FilterFromFixed.Value = FilterFrom.SelectedDate.ToString("yyyy-MM-dd");
}
< /script>

2010-07-29

Projected Fields with User Profile Properties in Sharepoint 2010

In SharePoint 2007, there was one list customization I had to do more than any other. A stakeholder would have a custom list, with a user field, and they would more often then not, want some profile fields to display in the list. So that they could filter the items by those profile fields. Things like State, or Office Location.

What i eventually had to do in SharePoint 2007, was kind of hacky, and really annoying to implement. Say if the user wanted the Office to be displayed in each row, i would create the Office field in the list definition as a Person field. Then make an event receiver, that on ItemAdding, would update the Office field to be the same user in the normal Person field, but instead of displaying the Name, i would display the user profile field that the stakeholder wanted.

So with multiple columns, i would end up with something like this:

[image]

But with SharePoint 2010 this problem goes away. Enter list joins and projected fields. What this allows is having one list, and showing value from a joined list. Things did not go as smoothly as i hoped though.

So i went into the column create screens and cycled through the different field types. I was disappointed that the person field did not have what i wanted. Only the lookup field type had the projected fields. Well i could live with that, but it would not be the ideal solution. Because you would not be able to make use of the people picker, it would just be a very large dropdown.

But when i went to assign the lookup table to the hidden "User Information List", well, it was hidden. This list if you dont know, holds a copy of the user profile fields marked as replicatable. Sharepoint takes care of keeping it in sync with the values in the SSP or Application Service.

I suspected that while it was hidden, i could still make the join, just not through the interface. So i went hunting from some scripts, preferably powershell to create this projected fields. I found them on msdn, and it looked pretty straight forward. It got me thinking.

Hang on though, a person field is just a lookup field, so i could go back to my orignial plan of joining the custom list to the "User Information List", but using a Person field instead of a lookup.

To my shock, everything work out as i had hoped for since the start. Effectively i have reduced a days work of hassle and deployment, to a few lines of powershell.

Scripts and screen shots to come later.