Last month I posted on how to create a SharePoint document library using a CRM callout. Using a document library per entity is fine if you aren’t creating a large number of entities, and the documents in the libraries are not related. However, in the CRM world it is very likely that you will have multiple opportunities per account or multiple cases for one account.
Based on this scenario there are a couple different ways that you could structure the document libraries. First is to have a document library per account and create a folder for each new opportunity or case. The second structure would be a single document library with a folder for each account and sub folders for each opportunity or case. Both of these solutions reduce the overhead of creating lots of document libraries.
However, be aware of the recommended limits for SharePoint document libraries. The recommendation is less than a 1000 document libraries per site. For many businesses this would be exceeded very quickly. In addition, it is recommended to keep any document library view under 1000 (WSS v2) or 2000 (WSS v3) items and the maximum number or documents per library under 2 million. One last limitation that needs to be mentioned is the URL length which is related to folder depth and filename length. The maximum URL length is 260 characters.
Link: http://www.microsoft.com/technet/windowsserver/sharepoint/V2/fsdoclib.mspx
Well based on all of this information how would I structure a SharePoint site for a company that has significant repeat interactions with around 50 accounts? Since the business has only a few accounts with frequent interaction I would create a document library per account and use subfolders for each opportunity.
For simplicity you can use the account name as the name for the document library. However, be aware that very long names or duplicate names will cause problems. If this is a significant problem then you can use a truncated name attribute and the ID guid. This won’t be very user friendly but will generate a more predicable library name. The same issues exist for opportunities. At this point I would suggest truncating the Opportunity name (subject) to ~50 characters and appending the opportunityID when creating the folder, because I see many repeated opportunities titles.
So now we have an idea of how to the library structure will be we need to handle a couple of key tasks to make this work.
For creating the account document library use the code from my previous post.
Link: http://blogs.msdn.com/crm/archive/2006/09/11/750609.aspx
For creating a folder in a document library use the UpdateListItems method of the lists web service. This method takes two parameters the list name, and an Xml string called a batch. This Xml string can contain a set of method elements which describe the type of updates to execute.
API Reference: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/spptsdk/html/soapmListsUpdateListItems_SV01034352.asp
Here is a sample batch string for a folder:
<Batch OnError=”Return” RootFolder=””>
<Method ID=”1″ Cmd=”New”>
<Field Name=”ID”>
New
</Field>
<Field Name=”FSObjType”>
1
</Field>
<Field Name=”BaseName”>
foldername
</Field>
</Method>
</Batch>
In the sample above there are two key fields. FSObjType is and system column that document libraries have which determines if the item is a folder (1) or document. BaseName is the file name or folder name in this case.
The code snippet below builds a batch Xml string and sends the batch to the SharePoint server creating the folder in the document library specified by the listname parameter.
public static System.Xml.XmlNode CreateFolder(string listName, string folderName)
{
System.IO.StringWriter sw = new System.IO.StringWriter();
System.Xml.XmlTextWriter xw = new System.Xml.XmlTextWriter(sw);
xw.WriteStartDocument();
// build batch node
xw.WriteStartElement(“Batch”);
xw.WriteAttributeString(“OnError”, “Return”);
xw.WriteAttributeString(“RootFolder”, “”);
// Build method node
xw.WriteStartElement(“Method”);
// Set transaction ID
xw.WriteAttributeString(“ID”, Guid.NewGuid().ToString(“n”));
xw.WriteAttributeString(“Cmd”, “New”);
// Build field ID
xw.WriteStartElement(“Field”);
xw.WriteAttributeString(“Name”, “ID”);
xw.WriteString(“New”);
xw.WriteEndElement(); // Field end
// Build FSObjType
xw.WriteStartElement(“Field”);
xw.WriteAttributeString(“Name”, “FSObjType”);
xw.WriteString(“1”); // 1= folder
xw.WriteEndElement(); // Field end
// Build Base Name field from folder
xw.WriteStartElement(“Field”);
xw.WriteAttributeString(“Name”, “BaseName”);
xw.WriteString(folderName);
xw.WriteEndElement(); // Field end
// Close Method & Batch elements
xw.WriteEndElement(); // Method end
xw.WriteEndElement(); // Batch end
xw.WriteEndDocument();
System.Xml.XmlDocument batchElement = new System.Xml.XmlDocument();
batchElement.LoadXml(sw.GetStringBuilder().ToString());
//Setup web service
DocLibraryCallouts.SharePointLists.Lists listService = new DocLibraryCallouts.SharePointLists.Lists();
listService.Credentials = new System.Net.NetworkCredential(“someuser”, “somepassword”, “somedomain”);
// send update request to sharepoint to create the document folder
System.Xml.XmlNode result = listService.UpdateListItems(listName, batchElement);
return result;
}
These last two post should provide the basics working with document libraries using CRM callouts. I hope this helps you integate Microsoft CRM and the SharePoint products. If you have any other ideas for integration between Microsoft CRM and SharePoint leave suggestions in the comments section.
Hope this helps,
Rich Dickinson