This is part three of a multi-part series on how to make your SharePoint applications ECM aware, by taking advantage of the new ECM features in SP2010. My last post explained how you could leverage the new feature “Document Sets” to put a process around your document management. The post explained how you could do this using the server side object model and how difficult it is to try using document sets remotely through any built-in SharePoint remote API like the client object model or a web service. Well after much research it is possible to provision document sets with the client object model, albeit, a bit convoluted.
I started by looking at the way the server object model allows you to create a document set. This is done by using the static Create method of the DocumentSet class in the Microsoft.Office.DocumentManagement assembly. Below is code showing how simple this can be done. The method takes the folder where the document set will be located, the content type id for the document set you are creating, the name of the new document set, a hashtable of properties to be given to the document set, and most importantly a bool value stating whether to provision any default documents to the new document set. Very easy from a server side point a view, however, doing the same from the client object model proved to be difficult.
public static void CreateDocumentSet(SPFolder folder, |
When trying to do this through the client object model I remembered that there are many settings for a document set and these settings are used when a new document set is provisioned. For instance, you can choose the allowable content types, the default documents, and the shared properties among the documents and whether the default documents have the document set name appended to them.
Below is the AddDocSet method which uses the client object model to create a new document set based on a document set content type. I have included this top level method along with another method in this posting, to show you all the different steps needed to accomplish what the server side object model does so easily. The full code which is included in the DocumentSetsRemote static class can be downloaded here.
The AddDocSet method takes the following arguments, the url to the site, the name of the document library you want to create the document set in, the name of the document set content type, the name of the new document set you want to create, and a hash table of properties for the metadata you want to give the new document set. These would include the display name of the SharePoint field along with the value.
public static void AddDocSet(string siteUrl, string listName, clientContext.Load(clientContext.Site); ContentTypeCollection listContentTypes = list.ContentTypes; var result = clientContext.LoadQuery(listContentTypes.Where clientContext.ExecuteQuery(); ContentType targetDocumentSetContentType = result.FirstOrDefault(); ListItemCreationInformation newItemInfo = new ListItemCreationInformation(); newListItem["ContentTypeId"] = targetDocumentSetContentType.Id.ToString(); clientContext.Load(list); List<ContentTypeId> allowedContentTypes = null; //get the allowed content types from the document set's schema
clientContext.Load(folder, f => f.UniqueContentTypeOrder); if (allowedContentTypes != null) clientContext.ExecuteQuery(); //update the document set's docset_LastRefresh property //set default documents and shared properties } |
The first step is to use the client object model to create a folder listitem and set the contenttypeid field to the content type id of the type of document set you are creating. The second step is to set the “allowable content types” that this document set can contain. So when configuring a document set I was wondering how to obtain all this configuration data via the client object model. The allowable content types, default documents, shareable properties and other information is stored in the the SchemaXml property of the ContentType class. I used xml linq to pull this data from the schema as show in the GetAllowableContentTypes method below:
private static List<ContentTypeId> GetAllowedContentTypes(string listSchemaXml, List<string> schemaContentypeIds = new List<string>(); ; XNamespace act = XDocument document = XDocument.Parse(listSchemaXml); var result = from e in document.Descendants().Elements("XmlDocuments") if (result != null && result.Count() > 0) foreach (string schemaContentTypeId in schemaContentypeIds) } return allowableContentTypeIds; } |
This method returns a list of content type ids to set the new document set’s UniqueContentTypeOrder property. You will find in the downloadable code other methods using the same technique to obtain information.
The next step is to update the “docset_LastRefresh” property of the document set. Why? This apparently is a stamp of approval by the SharePoint UI that the document set was configured correctly. If you do not set this, then you will have a nagging yellow bar at the top of the SharePoint UI stating that the document set is missing some content types and needs updating. You can click on the link and it will generate the property for you. This value is stored in the SPFolder.Properties property bag. Unfortunately, the client object model does not support this. So, the UpdateFolder method uses the Lists.asmx web service to update this.
The final step to create a document set is to provision the default documents that are defined. These are the documents that are created by default whenever a new document set is created.
When creating the default documents there are many details that you must implement using the client object model. First, you must get the document from the server, assign the appropriate content type, assign any shareable properties, and optionally append the name of the document set to the document’s name. Once this is done you add the document to the document set. Provisioning default documents is inefficient when doing it remotely. This is because the default document must be downloaded from the list’s forms folder and then uploaded again into the document set. Unfortunately, there is no way around this. This is all implemented in the SetDefaultDocuments method in the downloadable code. The only problem I had was with shareable document set fields that had the same display name as fields defined on the list. The client object model cannot handle duplicate field names.
You can download all the code listed here along with other private methods for the complete solution. The code is contained in one static class called DocumentSetsRemote.cs.
In summary, using document sets can be done remotely without having to use a custom web service. SharePoint does not expose any out of the box web services that deal explicitly with document sets, however, it does have the client object model and other standard web services you can take advantage of. With some basic research you can make your remote SharePoint applications ECM aware and leverage the new “Document Set” feature.