Microsoft Dynamics 365 Blog

In March 2008, Reuben Krippner presented two breakout sessions at Convergence US on Extensibility with Microsoft Dynamics CRM.

During these sessions I covered a number of live demonstrations of how you can extend and integrate Microsoft Dynamics CRM. One of the “big hit” demos involved the creation of contextual document libraries and folders triggered by Microsoft Dynamics CRM 4.0. I have packaged up this example as a hands-on-lab for you to try for yourself.

A few explanatory notes first! As always, the code samples are supplied as is with no support or warranty provided by Microsoft. Feel free to take this code and modify and extend as you see fit. Special thanks go to Rich Dickinson from the Microsoft Dynamics CRM product group who set out the concepts and some code snippets for me to borrow and extend! This post covers solutions for both Microsoft Dynamics CRM 3.0 and 4.0.

Steps for Microsoft Dynamics CRM Version 3.0:

For Microsoft Dynamics CRM 3.0 we will create a post-create callout component that will create a contextual document library within SharePoint whenever a new Account record is created. SharePoint provides us with web services that allow us to programmatically create document libraries. The code sample also then writes the URL of the document library to custom attributes in the Account entity. The contextual document library is displayed in an iFrame by some custom JavaScript in the onLoad event for the Account form in Microsoft Dynamics CRM.

Steps to follow:

Step 1: We need to add some custom attributes to the Account and Opportunity entities, these attributes are used to store the location of the contextual document libraries and folders that we create via the callout component. Create the following attribute for the Account entity:

New_sharepointdocumentlibraryurl: nvarchar – allow a reasonable length for the URL value

Step 2: Save the changes

Step 3: Create the following attribute for the Opportunity entity:

New_sharepointdocumentlibraryurl: nvarchar – allow a reasonable length for the URL value

Step 4: Save the changes

Step 5: Publish the changes so that the CRM web services are up to date with our new attributes.

Step 6: Create a class library project in Visual Studio to create our post-callout component (Remember that in Microsoft CRM 3.0 this has to be a .NET 1.1 assembly).

Step 7: Add web references for the following:

1. Sharepoint, typically this is lists.asmx and there may be a number of these web service endpoints due to multiple SharePoint sites on your designated server. SharePoint is designed so that the web services are virtualized at every site level. All of the web services binaries are located in the <site>/_vti_bin directory. For example: http://<sharepointservername>/_vti_bin/lists.asmx

2. Microsoft Dynamics CRM (CRM Service) which is typically found at http://<yourcrmservername>/mscrmservices/2006/crmservice.asmx.

Step 8: Add a reference to the following dll: Microsoft.Crm.Platform.Callout.Base.dll to bind to the CRM 3.0 callout interface.

Step 9: Ensure you are editing the main class file in your project (I called this file doclist.cs) Look through this code and make sure you change any System.Net.NetworkCredential to a valid username, password and domain. Also look through the code for any references to yoursharepointservername and change this to a valid server name for your SharePoint location.

   1: using System; 
   2: using System.IO; 
   3: using System.Text; 
   4: using System.Xml; 
   5: using Microsoft.Crm.Callout;
   6: using DocList.CrmSdk; 
   7:  
   8: namespace crmsp.libraries 
   9: { 
  10:     public class doclist : CrmCalloutBase 
  11:     { 
  12:  
  13:         public static System.Xml.XmlNode CreateFolder(string listName, string folderName) 
  14:         { 
  15:             //Creating a SharePoint document folder under a library requires us to pass an Xml document to the web service 
  16:             // 
  17:             // The XML document looks like this: 
  18:             // 
  19:             //  <Batch OnError="Return" RootFolder=""> 
  20:             //      <Method ID="1" Cmd="New"> 
  21:             //            <Field Name="ID">New</Field> 
  22:             //            <Field Name="FSObjType">1</Field> 
  23:             //            <Field Name="BaseName">foldername</Field> 
  24:             //      </Method> 
  25:             //  </Batch> 
  26:             // Let's set up an XML document and populate it with the settings for our new document folder 
  27:             System.IO.StringWriter sw = new System.IO.StringWriter(); 
  28:             System.Xml.XmlTextWriter xw = new System.Xml.XmlTextWriter(sw); 
  29:             xw.WriteStartDocument(); 
  30:  
  31:             // build batch node 
  32:             xw.WriteStartElement("Batch"); 
  33:             xw.WriteAttributeString("OnError", "Return"); 
  34:             xw.WriteAttributeString("RootFolder", ""); 
  35:  
  36:             // Build method node 
  37:             xw.WriteStartElement("Method"); 
  38:  
  39:             // Set transaction ID 
  40:             xw.WriteAttributeString("ID", Guid.NewGuid().ToString("n")); 
  41:             xw.WriteAttributeString("Cmd", "New"); 
  42:  
  43:             // Build field ID 
  44:             xw.WriteStartElement("Field"); 
  45:             xw.WriteAttributeString("Name", "ID"); 
  46:             xw.WriteString("New"); 
  47:             xw.WriteEndElement(); // Field end 
  48:  
  49:             // Build FSObjType 
  50:             xw.WriteStartElement("Field"); 
  51:             xw.WriteAttributeString("Name", "FSObjType"); 
  52:             xw.WriteString("1");  // 1= folder 
  53:             xw.WriteEndElement(); // Field end 
  54:  
  55:             // Build Base Name field from folder 
  56:             xw.WriteStartElement("Field"); 
  57:             xw.WriteAttributeString("Name", "BaseName"); 
  58:             xw.WriteString(folderName); 
  59:             xw.WriteEndElement(); // Field end 
  60:  
  61:             // Close Method & Batch elements 
  62:             xw.WriteEndElement(); // Method end 
  63:             xw.WriteEndElement(); // Batch end 
  64:             xw.WriteEndDocument(); 
  65:             System.Xml.XmlDocument batchElement = new System.Xml.XmlDocument(); 
  66:             batchElement.LoadXml(sw.GetStringBuilder().ToString()); 
  67:  
  68:             //Setup web service 
  69:             Lists listService = new Lists(); 
  70:             listService.Credentials = new System.Net.NetworkCredential("username", "password", "domain name"); 
  71:  
  72:             // send update request to sharepoint to create the document folder 
  73:             System.Xml.XmlNode result = listService.UpdateListItems(listName, batchElement); 
  74:             return result; 
  75:         } 
  76:  
  77:         public override void PostCreate(CalloutUserContext userContext, CalloutEntityContext entityContext, string postImageEntityXml) 
  78:         { 
  79:             //SharePoint Document Libraries have a type code of 101 
  80:             Int32 spDocLibraryListType = 101; 
  81:  
  82:             //If this is a create of an account then create a document library 
  83:             if (entityContext.EntityTypeCode == 1) 
  84:             { 
  85:                 // Load the postImageEntityXml and use an XPath 
  86:                 // query to locate the name field value. 
  87:                 XmlDocument xd = new XmlDocument(); 
  88:                 xd.LoadXml(postImageEntityXml); 
  89:                 // Initialize a NameTable object. 
  90:                 NameTable nt = new NameTable(); 
  91:                 // Initialize a namespace manager. 
  92:                 XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt); 
  93:                 // Add the required prefix/namespace pairs to the namespace 
  94:                 // manager. Add a default namespace first. 
  95:                 nsmgr.AddNamespace("crm","http://schemas.microsoft.com/crm/2006/WebServices"); 
  96:                 nsmgr.AddNamespace("xsi","http://www.w3.org/2001/XMLSchema-instance"); 
  97:                 XmlNode node = xd.SelectSingleNode("//crm:Property[@Name='name']/crm:Value", nsmgr); 
  98:                 // Grab the node's InnerText property to name our SharePoint Document Library. 
  99:                 if (node != null) 
 100:                 { 
 101:                     string accountName = node.InnerText; 
 102:                     //string listName = node.InnerText + "_" + DateTime.Now.ToString("yyyyMMdd_hhmmss"); 
 103:                     //Call the SharePoint Web Service to create a document library 
 104:                     Lists listService = new Lists(); 
 105:                     listService.Credentials = new System.Net.NetworkCredential("user name", "password", "domain name"); 
 106:                     //System.Xml.XmlNode result = listService.AddList(listName, accountName + " Document Library", spDocLibraryListType); 
 107:                     System.Xml.XmlNode result = listService.AddList(accountName, accountName + " Document Library", spDocLibraryListType); 
 108:                     //grab the return xml 
 109:                     string returnXml = result.InnerXml.ToString(); 
 110:                     //update Microsoft CRM record with the return xml 
 111:                     CrmService service = new CrmService(); 
 112:                     service.Credentials = System.Net.CredentialCache.DefaultCredentials; 
 113:  
 114:                     // Create the account object. 
 115:                     account account = new account(); 
 116:  
 117:                     // Set the properties of the account object to be updated. 
 118:                     account.new_sharepointdocumentlibraryurl = "http://yoursharepointservername/" + accountName + "/Forms/AllItems.aspx"; 
 119:  
 120:                     // accountid is a key that references the ID of the account to be updated. 
 121:                     account.accountid = new Key(); 
 122:  
 123:                     // account.accountid.Value is the GUID of the record to be changed. 
 124:                     account.accountid.Value = entityContext.InstanceId; 
 125:  
 126:                     // Update the account. 
 127:                     service.Update(account);            
 128:                 } 
 129:             } 
 130:  
 131:             //If this is a create of an opportunity then create a folder under the account's document library 
 132:             if (entityContext.EntityTypeCode == 3) 
 133:             { 
 134:                 //If the Opportunity is linked to an account then we want to create a document folder 
 135:                 // 
 136:                 // Load the postImageEntityXml and use an XPath 
 137:                 // query to locate the name field value. 
 138:                 XmlDocument xd = new XmlDocument(); 
 139:                 xd.LoadXml(postImageEntityXml); 
 140:                 // Initialize a NameTable object. 
 141:                 NameTable nt = new NameTable(); 
 142:                 // Initialize a namespace manager. 
 143:                 XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt); 
 144:                 // Add the required prefix/namespace pairs to the namespace 
 145:                 // manager. Add a default namespace first. 
 146:                 nsmgr.AddNamespace("crm", "http://schemas.microsoft.com/crm/2006/WebServices"); 
 147:                 nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); 
 148:                 XmlNode node = xd.SelectSingleNode("//crm:Property[@Name='customerid']/crm:Value[@type='account']", nsmgr); 
 149:                 // Grab the node's InnerText property to see if this opportunity is related to an account. 
 150:                 if (node != null) 
 151:                 { 
 152:                     //this node gives us the Guid of the Account record 
 153:                     string strAccountId = node.InnerText; 
 154:                     //we now need to query the account to grab the SharePoint document library name 
 155:                     CrmService service = new CrmService(); 
 156:                     service.Credentials = System.Net.CredentialCache.DefaultCredentials; 
 157:  
 158:                     //we'll also grab the Title of the sales Opportunity for naming our SharePoint folder 
 159:                     XmlNode nodeTitle = xd.SelectSingleNode("//crm:Property[@Name='name']/crm:Value", nsmgr); 
 160:  
 161:                     // Create the column set object that indicates the fields to be retrieved. 
 162:                     ColumnSet cols = new ColumnSet(); 
 163:                     // Set the properties of the column set. 
 164:                     cols.Attributes = new string[] { "new_sharepointdocumentlibraryname" }; 
 165:                     // accountGuid is the GUID of the record being retrieved. 
 166:                     Guid accountGuid = new Guid(strAccountId); 
 167:                     // Retrieve the account. 
 168:                     // The EntityName indicates the EntityType of the object being retrieved. 
 169:                     account account = (account)service.Retrieve(EntityName.account.ToString(), accountGuid, cols); 
 170:  
 171:                     //OK, now we have the sharepoint document library name we can create a document folder under it 
 172:                     //the folder name will be "Sales Opp" + the Guid of the Opportunity record 
 173:                     //string strFolderName = "Sales Opp - " + nodeTitle.InnerText + "_" + DateTime.Now.ToString("yyyyMMdd_hhmmss"); 
 174:                     string strFolderName = "Sales Opp - " + nodeTitle.InnerText; 
 175:                     XmlNode xmlResult = CreateFolder(account.new_sharepointdocumentlibraryname, strFolderName); 
 176:  
 177:                     //Finally, we need to update the opportunity with the folder location 
 178:                     // Create an opportunity object. 
 179:                     opportunity opportunity = new opportunity(); 
 180:  
 181:                     // Set the properties of the opportunity object to be updated. 
 182:                     opportunity.new_sharepointdocumentlibraryurl = "http://yoursharepointserver/" + account.new_sharepointdocumentlibraryname + "/Forms/AllItems.aspx?RootFolder=/" + account.new_sharepointdocumentlibraryname + "/" + strFolderName; 
 183:  
 184:                     // opportunityid is a key that references the ID of the opportunity to be updated. 
 185:                     opportunity.opportunityid = new Key(); 
 186:  
 187:                     // opportunity.Value is the GUID of the record to be changed. 
 188:                     opportunity.opportunityid.Value = entityContext.InstanceId; 
 189:  
 190:                     // Update the opportunity. 
 191:                     service.Update(opportunity);            
 192:                 } 
 193:             } 
 194:         } 
 195:     } 
 196: }

Step 10: Compile your new callout component.

Step 11: Copy the dll file created into the \server\bin\assembly folder on your CRM Server(s).

Step 12: Add the Callout.Config.xml snippet into your callout.config file.

<callout.config version=”1.0″ xmlns=” http://schemas.microsoft.com/crm/2006/callout/”>

<callout entity=”account” event=”PostCreate”>

<subscription assembly=”CRM_DOCS.dll”

class=”crmsp.libraries.doclist”

onerror=”abort”>

</subscription>

</callout>

</callout.config>

Step 13: Run IISReset to enable the new callout event

Step 14: We now need to configure the iFrames in the Account and Sales Opportunity entities to display our contextual document libraries or folders. Starting with Account form design: add a new tab called Document Library and then add a new iFrame called IFRAME_Sharepoint

clip_image002

clip_image003

Step 15: Next we want to add in the OnLoad logic on the Account form to set the URL of the SharePoint iFrame to display our contextual document library.

// OnLoad Event to set the iFrame URL for the SharePoint Library.

var CRM_FORM_TYPE_CREATE = 1;

var CRM_FORM_TYPE_UPDATE = 2;

////////////////////////////////////////////////////////////////////////////////

// Set SharePoint Document Library

////////////////////////////////////////////////////////////////////////////////

// we’ll update the iFrame src property if this is an update form

if (crmForm.FormType == CRM_FORM_TYPE_UPDATE)

{

var sUrl=crmForm.all.new_sharepointdocumentlibraryurl.DataValue;

crmForm.all.IFRAME_SharePoint.src = sUrl;

}

Step 16: Save the changes to the Account Entity.

Step 17: Now, working with the Opportunity entity: add a new tab called Document Folder and then add a new iFrame called IFRAME_Sharepoint.

clip_image004

clip_image005

Step 18: We now need to add the OnLoad logic to the Opportunity form.

// OnLoad Event to set the sharepoint document library iFrame

var CRM_FORM_TYPE_CREATE = 1;

var CRM_FORM_TYPE_UPDATE = 2;

////////////////////////////////////////////////////////////////

// Set SharePoint Document Folder

////////////////////////////////////////////////////////////////

// we’ll update the iFrame src property if this is an update form

if (crmForm.FormType == CRM_FORM_TYPE_UPDATE)

{

var sUrl=crmForm.all.new_sharepointdocumentlibraryurl.DataValue;

crmForm.all.IFRAME_SharePoint.src = sUrl;

}

Step 19: Finally, save changes to the Opportunity entity and Publish all your changes. The result should be that a new document library is created whenever a new Account record is added to Microsoft Dynamics CRM and a new Document Folder for each Sales Opportunity is created when Sales Opportunities are added to that Account record.


Steps for Microsoft Dynamics CRM Version 4.0:

The solution is very similar for Microsoft Dynamics CRM 4.0! We call the same SharePoint Web Services but the Microsoft Dynamics CRM platform coding is somewhat different!

For Microsoft Dynamics CRM 4.0 we will create 2 post-create plug-in components. The first will create a contextual document library within SharePoint whenever a new Account record is created. The second will create a document folder within our document library within SharePoint whenever a new opportunity is added to an account.

Steps to follow:

Run Steps 1 – 5 from the CRM 3.0 solution above to create the attributes we need to store the URL for our SharePoint Library or Folder.

Step 1: Create a class library project in Visual Studio to create our CRM 4.0 Plug-In component for the Account Create transaction.

Step 2: Add a web reference for SharePoint, typically this is lists.asmx and there may be a number of these web service endpoints due to multiple SharePoint sites on your designated server. SharePoint is designed so that the web services are virtualized at every site level. All of the web services binaries are located in the <site>/_vti_bin directory. For example: http://<sharepointservername>/_vti_bin/lists.asmx

Step 3: Add references to the following dll’s: Microsoft.crm.sdk.dll and Microsoft.crm.sdktypeproxy.dll, these are found in the bin folder where you have unpacked the crm sdk. Add another reference to system.web.services into your project.

Step 4: Ensure you are editing the main class file in your project (I called this file plugin.cs) Look through this code and make sure you change any System.Net.NetworkCredential to a valid username, password and domain. Also look through the code for any references to yoursharepointservername and change this to a valid server name for your SharePoint location.

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Text;
   4: using Microsoft.Crm.Sdk;
   5: using Microsoft.Crm.SdkTypeProxy;
   6: using AccountCreatePlugin.SharePoint;
   7:  
   8: namespace MSCRMSharePoint
   9: {
  10:     public class UpdateAccountOnCreate : IPlugin
  11:     {
  12:         #region IPlugin Members
  13:         public void Execute(IPluginExecutionContext context)
  14:         {
  15:             //First we'll grab the name of our account and its GUID
  16:             DynamicEntity entity = (DynamicEntity)context.InputParameters.Properties[ParameterName.Target];
  17:             string accountName = entity["name"].ToString();
  18:             string accountId = context.OutputParameters.Properties["id"].ToString();
  19:  
  20:             //SharePoint Document Libraries have a type code of 101 
  21:             Int32 spDocLibraryListType = 101;
  22:             
  23:             //Call the SharePoint Web Service to create a document library 
  24:             Lists listService = new Lists();
  25:             listService.Credentials = new System.Net.NetworkCredential("username", "password", "domain name");
  26:             System.Xml.XmlNode SPresult = listService.AddList(accountName, accountName + " Document Library", spDocLibraryListType);
  27:             //grab the return xml 
  28:             string returnXml = SPresult.InnerXml.ToString();
  29:  
  30:             //Now we'll update our account record with the URL of the contextual SP library
  31:             DynamicEntity account = new DynamicEntity();
  32:             account.Name = EntityName.account.ToString();
  33:             account["accountid"] = new Key(new Guid(accountId));
  34:             account["new_sharepointdocumentlibraryurl"] = "http://yoursharepointservername/" + accountName + "/Forms/AllItems.aspx";
  35:  
  36:             //Using the iPlugIn interface we create a reference to the CrmService web service
  37:             ICrmService service = context.CreateCrmService(true);
  38:             service.Update(account);
  39:         }
  40:         #endregion
  41:     }
  42: }

Step 5: Compile your new plug-in component.

Step 6: Register this plug-in with the platform – I suggest you use the Plug-In registration tool which is found in the sdk \sdk\tools\pluginregistration folder. You can either register this synchronously or asynchronously – it’s your choice!

Step 7: Create a class library project in Visual Studio to create our CRM 4.0 Plug-In component for the Opportunity Create transaction.

Step 8: Add a web reference for SharePoint, typically this is lists.asmx and there may be a number of these web service endpoints due to multiple SharePoint sites on your designated server. SharePoint is designed so that the web services are virtualized at every site level. All of the web services binaries are located in the <site>/_vti_bin directory. For example: http://<sharepointservername>/_vti_bin/lists.asmx

Step 9: Add references to the following dll’s: Microsoft.crm.sdk.dll and Microsoft.crm.sdktypeproxy.dll, these are found in the bin folder where you have unpacked the crm sdk. Add another reference to system.web.services into your project.

Step 10: Ensure you are editing the main class file in your project (I called this file plugin.cs) Look through this code and make sure you change any System.Net.NetworkCredential to a valid username, password and domain. Also look through the code for any references to yoursharepointservername and change this to a valid server name for your SharePoint location.

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Text;
   4: using OpportunityCreatePlugin.SharePoint;
   5: using Microsoft.Crm.Sdk;
   6: using Microsoft.Crm.SdkTypeProxy;
   7: using System.Xml;
   8:  
   9: namespace MSCRMSharePoint
  10: {
  11:     public class UpdateOpportunityOnCreate : IPlugin
  12:     {
  13:         #region IPlugin Members
  14:  
  15:         public static System.Xml.XmlNode CreateFolder(string listName, string folderName)
  16:         {
  17:             //Creating a SharePoint document folder under a library requires us to pass an Xml document to the web service 
  18:             // 
  19:             // The XML document looks like this: 
  20:             // 
  21:             //  <Batch OnError="Return" RootFolder=""> 
  22:             //      <Method ID="1" Cmd="New"> 
  23:             //            <Field Name="ID">New</Field> 
  24:             //            <Field Name="FSObjType">1</Field> 
  25:             //            <Field Name="BaseName">foldername</Field> 
  26:             //      </Method> 
  27:             //  </Batch> 
  28:             // Let's set up an XML document and populate it with the settings for our new document folder 
  29:             System.IO.StringWriter sw = new System.IO.StringWriter();
  30:             System.Xml.XmlTextWriter xw = new System.Xml.XmlTextWriter(sw);
  31:             xw.WriteStartDocument();
  32:  
  33:             // build batch node 
  34:             xw.WriteStartElement("Batch");
  35:             xw.WriteAttributeString("OnError", "Return");
  36:             xw.WriteAttributeString("RootFolder", "");
  37:  
  38:             // Build method node 
  39:             xw.WriteStartElement("Method");
  40:  
  41:             // Set transaction ID 
  42:             xw.WriteAttributeString("ID", Guid.NewGuid().ToString("n"));
  43:             xw.WriteAttributeString("Cmd", "New");
  44:  
  45:             // Build field ID 
  46:             xw.WriteStartElement("Field");
  47:             xw.WriteAttributeString("Name", "ID");
  48:             xw.WriteString("New");
  49:             xw.WriteEndElement(); // Field end 
  50:  
  51:             // Build FSObjType 
  52:             xw.WriteStartElement("Field");
  53:             xw.WriteAttributeString("Name", "FSObjType");
  54:             xw.WriteString("1");  // 1= folder 
  55:             xw.WriteEndElement(); // Field end 
  56:  
  57:             // Build Base Name field from folder 
  58:             xw.WriteStartElement("Field");
  59:             xw.WriteAttributeString("Name", "BaseName");
  60:             xw.WriteString(folderName);
  61:             xw.WriteEndElement(); // Field end 
  62:  
  63:             // Close Method & Batch elements 
  64:             xw.WriteEndElement(); // Method end 
  65:             xw.WriteEndElement(); // Batch end 
  66:             xw.WriteEndDocument();
  67:             System.Xml.XmlDocument batchElement = new System.Xml.XmlDocument();
  68:             batchElement.LoadXml(sw.GetStringBuilder().ToString());
  69:  
  70:             //Setup web service 
  71:             Lists listService = new Lists();
  72:             listService.Credentials = new System.Net.NetworkCredential("username", "password", "domain name");
  73:  
  74:             // send update request to sharepoint to create the document folder 
  75:             System.Xml.XmlNode result = listService.UpdateListItems(listName, batchElement);
  76:             return result;
  77:         } 
  78:  
  79:         
  80:         public void Execute(IPluginExecutionContext context)
  81:         {
  82:             DynamicEntity entity = (DynamicEntity)context.InputParameters.Properties[ParameterName.Target];
  83:             string opportunityName = entity["name"].ToString();
  84:             string opportunityId = context.OutputParameters.Properties["id"].ToString();
  85:             Customer relatedCustomer = (Customer) entity["customerid"];
  86:             if (relatedCustomer.type == EntityName.account.ToString())
  87:             {
  88:                 Guid accountid = relatedCustomer.Value;
  89:                 // Retrieve account name
  90:                 ICrmService service = context.CreateCrmService(true);
  91:                 Microsoft.Crm.Sdk.Query.ColumnSet cols = new Microsoft.Crm.Sdk.Query.ColumnSet(new string[] { "name", "new_sharepointdocumentlibraryurl" });
  92:                 account account = (account) service.Retrieve("account", accountid, cols);
  93:                 string strSPFolderName = "Sales Opportunity - " + opportunityName;
  94:  
  95:                 //Call the SharePoint web service to create our folder
  96:                 XmlNode xmlResult = CreateFolder(account.name, strSPFolderName);
  97:  
  98:                 //final task is to update the opportunity with the location of the new sharepoint folder
  99:                 DynamicEntity opportunity = new DynamicEntity();
 100:                 opportunity.Name = EntityName.opportunity.ToString();
 101:                 opportunity["opportunityid"] = new Key(new Guid(opportunityId));
 102:                 opportunity["new_sharepointdocumentlibraryurl"] = "http://yoursharepointservername/" + account.name + "/Forms/AllItems.aspx?RootFolder=/" + account.name + "/" + strSPFolderName;
 103:                 service.Update(opportunity);
 104:             }
 105:         }
 106:         #endregion
 107:     }
 108: }

Step 11: Compile your new plug-in component.

Step 12: Register this plug-in with the platform – I suggest you use the Plug-In registration tool which is found in the sdk \sdk\tools\pluginregistration folder. You can either register this synchronously or asynchronously – it’s your choice!

Finally, follow steps 14 through 19 of the CRM 3.0 solution above to set up the iFrames and client-side JavaScript functions.

Have fun with these samples! Good programming practice suggests that you will want to add appropriate error handling!

Kind regards,

Reuben Krippner

We're always looking for feedback and would like to hear from you. Please head to the Dynamics 365 Community to start a discussion, ask questions, and tell us what you think!