Auto Create Sharepoint Folder in CRM online
Many of our customers annoyed and frustrated with popup that appears when they click on documents navigation link on a record to add documents. So I thought it can be easily addressed using workflow/plugin on create of record by automatically adding the SharePoint location record.But that did not resolve problem still users prompted with popup. When i googled on this topic i found one post from Scott but that requires to have user name and password of the sharepoint admin.
http://develop1.net/public/post/SharePoint-Integration-Reloaded-e28093-Part-3.aspx
After lot of trial and error just started with my best friend fiddler to capture request and response that were posted on click of the popup window. CRM online uses CRM API message “CreateFolder” to create sharepoint folder and location record. I tried to use this “CreateFolder” message in my custom workflow step to create folder but received error message “This requested can’t be executed in sandbox mode” then tried with javascript to post same message and it worked fine.
Here is complete script to auto create sharepoint folder for CRM online. Add below script to your script resource file and save and publish it. Then call function createDocFolder on onload of the page that will automatically create sharepoint and location folder.
//Function to be called on onload of the page.
var myFormType = null;
function createDocFolder() {
Xrm.Page.data.entity.addOnSave(function () {
myFormType = Xrm.Page.ui.getFormType();
});
if (myFormType === 1 && Xrm.Page.ui.getFormType() !== 1) { // calls this method only when new record is saved.
var clientUrl = Xrm.Page.context.getClientUrl();
var xmlhttp = new XMLHttpRequest();
xmlhttp.open(“POST”, clientUrl + “/XRMServices/2011/Organization.svc/web”, false);
xmlhttp.setRequestHeader(“Accept”, “application/xml, text/xml, */*”);
xmlhttp.setRequestHeader(“Content-Type”, “text/xml; charset=utf-8”);
xmlhttp.setRequestHeader(“SOAPAction”, “http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute”);
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
alert( xmlhttp.responseText);
}
};
xmlhttp.send(buildCreateReq());
}
}
//Function to build request
function buildCreateReq() {
var recordId = Xrm.Page.data.entity.getId().replace(“{“, “”).replace(“}”, “”);
return “<s:Envelope xmlns:s=\”http://schemas.xmlsoap.org/soap/envelope/\”>” +
” <s:Header>” +
” <SdkClientVersion xmlns=\”http://schemas.microsoft.com/xrm/2011/Contracts\”></SdkClientVersion>” +
” </s:Header>” +
” <s:Body>” +
“<Execute xmlns=\”http://schemas.microsoft.com/xrm/2011/Contracts/Services\” xmlns:i=\”http://www.w3.org/2001/XMLSchema-instance\”>” +
” <request i:type=\”b:CreateFolderRequest\” xmlns:a=\”http://schemas.microsoft.com/xrm/2011/Contracts\” xmlns:b=\”http://schemas.microsoft.com/crm/2011/Contracts\”>” +
” <a:Parameters xmlns:b=\”http://schemas.datacontract.org/2004/07/System.Collections.Generic\”>” +
” <a:KeyValuePairOfstringanyType>” +
” <b:key>FolderName</b:key>” +
” <b:value i:type=\”c:string\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + Xrm.Page.data.entity.getPrimaryAttributeValue() + “_” + recordId + “</b:value>” +
” </a:KeyValuePairOfstringanyType>” +
” <a:KeyValuePairOfstringanyType>” +
” <b:key>RegardingObjectType</b:key>” +
” <b:value i:type=\”c:int\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + Xrm.Page.context.getQueryStringParameters().etc + “</b:value>” +
” </a:KeyValuePairOfstringanyType>” +
” <a:KeyValuePairOfstringanyType>” +
” <b:key>RegardingObjectId</b:key>” +
” <b:value i:type=\”c:string\” xmlns:c=\”http://www.w3.org/2001/XMLSchema\”>” + recordId + “</b:value>” +
” </a:KeyValuePairOfstringanyType>” +
” <a:KeyValuePairOfstringanyType>” +
” <b:key>DocumentType</b:key>” +
” <b:value i:nil=\”true\” />” +
” </a:KeyValuePairOfstringanyType>” +
” <a:KeyValuePairOfstringanyType>” +
” <b:key>ParentLocationId</b:key>” +
” <b:value i:nil=\”true\” />” +
” </a:KeyValuePairOfstringanyType>” +
” </a:Parameters>” +
” <a:RequestId i:nil=\”true\” />” +
” <a:RequestName>CreateFolder</a:RequestName>” +
” </request>” +
“</Execute>” +
“</s:Body>” +
“</s:Envelope>”;
}
Click here to Download script File, change the extention of the file to js from doc.
This is exactly what I need, but we are running MS CRM 2011, and I am a total JS nube. I tried the code and it did not work – any suggestions on changes I would have to make to get it to work in CRM 2011?
I followed you instructions, but got a Business Process Error:
Exception: Plugin ErrorincidentThe given key was not present in the dictionary.
TARGET SITE: TValue get_Item(TKey) Please contact your system administrator., Correlation Id: 2cdd536c-9812-49bf-b782-d237cba50af6, Initiating User: ab16005c-e9fc-403a-83e8-f7ed1d24811a
I tried using this code for CRM 2011, but it fails with a message that the deserializer has no knowledge of any type that maps to CreateFolderRequest. Any clue how to make this work for CRM 2011?
This works only on crm 2013/2015/2016 online and have not tested for on-premise
Hi,
I am trying to achieve the same. Do I need to use the JS web resource on entity such as accounts/contacts etc or on SharePoint related entities.
I tried using the JS web resource on the account and calling the function on form onload, but it is not working.
I am using, CRM 2016 online version.
Please help.
Thanks,
Krishna
Hello Krishna
In crm 2016 update microsoft released this as part of configuration. Check the below post that shows all the steps needed to configure this.
crm 2016 update 1 comes with this feature out of box. refer below link
Hi Chitrarasan,
Love this work you’ve done here!
I have the code above up and running, but I was wondering if you might be able to point me in the right direction on customizing the folder structure a bit.
Based on the JS above, the folder is generated in …site/custom_entity/record_name
Do you know how I can adjust to instead create the folder in: …/site/accounts/customer_record/custom_entity/record_name
Is this black magic?
We just like being able to keep all client documentation under the client folder instead of across multiple different siloed folders.
Any help would be greatly appreciated!
/Jeremy
creation of folder depends on the sharepoint site settings set while configuring. If you set to create folders based on account record or individual entity record.
You’re right! Just realized that myself and everything is working well. Thanks!
Hi to all, thanks for code but i have a problem.
I need to create this situation under some sub sites
sharepointsite/afros/public/account/nameaccount_guidaccount
sharepointsite/afros/private/account/nameaccount_guidaccount
sharepointsite/bono/public…
i change the code adding the relative path in the FolderName i get that the service create this site
sharepointsite/account/afros/public…i don’t want account after the sharepointsite…
It is possible?
Thanks
thank you so much for the code i exactly needed that in JS and NOT in c#, that’s perfect