17

I'm trying to add a custom web part (that is one I have written myself) using the new Javascipt OM available with SharePoint 2010. My solution is also running within the Sandbox.

I have it working correctly for the Content Editor Web Part (based on sample code), however when I replace the Content Editor Web Part definition with one for my own web part I get the following error:

---------------------------
Message from webpage
---------------------------
Request failed. The operation could not be completed because the Web Part is not on this page.
undefined
---------------------------
OK   
---------------------------

Things I have tested:

  1. I can successfully upload my .webpart definition to the web part gallery, and the web part works.
  2. I can successfully add the web part to the page where I'm programmatically trying to add it using the "Upload Web Part" feature.

This is the code I'm using to add the web part:

function addWebPart(serverRelativeUrl) {
//var webPartXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
//webPartXml = webPartXml + "<WebPart xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://schemas.microsoft.com/WebPart/v2\">  <Title>Content Editor</Title>  <FrameType>Default</FrameType>  <Description>Allows authors to enter rich text content.</Description>  <IsIncluded>true</IsIncluded>  <ZoneID>Main</ZoneID>  <PartOrder>0</PartOrder>  <FrameState>Normal</FrameState>  <Height />  <Width />  <AllowRemove>true</AllowRemove>  <AllowZoneChange>true</AllowZoneChange>  <AllowMinimize>true</AllowMinimize>  <AllowConnect>true</AllowConnect>  <AllowEdit>true</AllowEdit>  <AllowHide>true</AllowHide>  <IsVisible>true</IsVisible>  <DetailLink />  <HelpLink />  <HelpMode>Modeless</HelpMode>  <Dir>Default</Dir>  <PartImageSmall />  <MissingAssembly>Cannot import this Web Part.</MissingAssembly>  <PartImageLarge>/_layouts/images/mscontl.gif</PartImageLarge>  <IsIncludedFilter />  <Assembly>Microsoft.SharePoint, Version=14.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\" />  <PartStorage xmlns=\"http://schemas.microsoft.com/WebPart/v2/ContentEditor\" /></WebPart>";

var webPartXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
       "<webParts><webPart xmlns=\"http://schemas.microsoft.com/WebPart/v3\">" +
       "<metaData>" + 
       "<type name=\"Codezeven.Social.Views.WebParts.ItemViewTrackerWebPart, Codezeven.Social.Views, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c56ab109c2917056\" />" +
       "<importErrorMessage>Cannot import this Web Part.</importErrorMessage>" +
       "<Solution SolutionId=\"f5984dff-f7c0-4108-8c08-671bbb9b5df0\" xmlns=\"http://schemas.microsoft.com/sharepoint/\" />" +
       "</metaData>" +
       "<data><properties>" +
       "<property name=\"Title\" type=\"string\">ItemViewTrackerWebPart</property>" +
       "</properties></data>" + 
       "</webPart></webParts>";

clientContext = new SP.ClientContext.get_current();
var oFile = clientContext.get_web().getFileByServerRelativeUrl(serverRelativeUrl);

var limitedWebPartManager = oFile.getLimitedWebPartManager(SP.WebParts.PersonalizationScope.shared);

var oWebPartDefinition = limitedWebPartManager.importWebPart(webPartXml);
this.oWebPart = oWebPartDefinition.get_webPart();

limitedWebPartManager.addWebPart(oWebPart, 'Main', 0);

clientContext.load(oWebPart);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));}

function onQuerySucceeded() {

    alert('Web Part added: ' + oWebPart.get_title());
}
function onQueryFailed(sender, args) {

    alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}

UPDATE: Based on feedback from Wictor, I tried the following:

<?xml version="1.0" encoding="utf-8"?>
<webParts>
  <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
    <metaData> 
      <type name="Microsoft.SharePoint.WebPartPages.SPUserCodeWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
      <importErrorMessage>Cannot import this Web Part.</importErrorMessage>
    </metaData>
    <data>
      <properties>
        <property name="Title" type="string">ItemViewTrackerWebPart</property>
    <property name="SolutionId" type="string">f5984dff-f7c0-4108-8c08-671bbb9b5df0</property>
    <property name="AssemblyFullName" type="string">Codezeven.Social.Views, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c56ab109c2917056</property>
    <property name="TypeFullName" type="string">Codezeven.Social.Views.WebParts.ItemViewTrackerWebPart</property>
    <property name="Description" type="string">ViewTracker</property>
      </properties>
    </data>
  </webPart>
</webParts>

On this I'm getting a "Cannot Import Web Part" error. I think this is heading in the right direction, not sure if I have an issue in my .webpart file.

2
  • Confirmed that it does not work either way. Also tried using the .NET Client Object Model. Somewhere deep inside ASP.NET an exception is thrown when trying to create the SPUserCodeWebPart Jul 15, 2010 at 23:47
  • Thanks Wictor, really sucks, puts a big break on many of the streamlining I was hoping to be able to build into solutions. Jul 22, 2010 at 5:58

2 Answers 2

3

Try to add it using the SPUserCodeWebPart instead and pass the AssemblyFullName, TypeFullName and SolutionId parameters instead.

3

I have the exact same problem. Unfortunately, it doesn't look like it's possible to use a .webpart file for the wrapper web part, SPUserCodeWebPart, since the GetTypeId method in the SafeControls class in SharePoint explicitly checks for this and throws an exception if you try as evidenced by the following reflected code:

// Microsoft.SharePoint.ApplicationRuntime.SafeControls
internal static Guid GetTypeId(MD5HashProvider md5Provider, Type type, string assemblyName)
{
    if (type.Equals(typeof(SPUserCodeWebPart)))
    {
        throw SPUtility.GetStandardArgumentException("type");
    }
    return SafeControls.GetTypeIdUnsafe(md5Provider, type.FullName, assemblyName);
}

The reason we get the "Web Part is not on this page" error is that there is a slight difference in the way web parts are imported when using the client object model. There is also a difference in how sandboxed web parts are instantiated compared to farm-code web parts. These two difference together causes the import to fail.

When using the client object model to import web parts, the ImportWebPart_Client method on the server side SPLimitedWebPartManager object is called. This is basically a wrapper for the normal ImportWebPart method that returns an SPWebPartDefinition object instead of the web part itself. One attribute of this object is the web part's storage key guid that identifies this particular instance of the web part.

To get the storage key, ImportWebPart_Client calls GetStorageKey(WebPart) which first checks if the web part is registered in the SPLimitedWebPartManager by looking for it in the manager's private collection of registered web parts. Web parts are added to this collection when SharePoint calls the internal method SPWebPartManager.RegisterWebPart during the import process. The problem is that when the imported web part is sandboxed, this method is never called and that's when the Exception is thrown.

As far as I can tell, there's no way to add a sandboxed web part using the client object model. You will need some kind of farm code to do this. Maybe a small WCF service that imports and adds the .webpart file to a page using the regular ImportWebPart method.

You could also possibly add the sandboxed web part with a feature, and activate the feature using CSOM. Note that this feature can be sandboxed, so if you're in a multi-tenant environment like Office 365 or are prevented from deploying farm code for other reasons and must be able to add the web part dynamically from CSOM, this may be the best option.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.