Automatic provisioning of Organizations

Microsoft CRM does have a separate webservice for doing deployment related activities. There is a Deployment SDK especially for this webservice. You can download that here. One of the activities you can execute is automatic provisioning of new organizations. In this post I'll dive into the code required for this as well as some of the common issues while doing so.

Basically following the next steps should be enough:
- create an application
- add a web reference to: http:///mscrmservices/2007/crmdeploymentservice.asmx
- write the following code:


Organization org = new Organization();
org.UniqueName = txtName.Text;
org.FriendlyName = txtName.Text;
org.SqlServerName = ConfigurationManager.AppSettings["SqlServerName"];
org.SrsUrl = ConfigurationManager.AppSettings["SrsUrl"];
org.BaseCurrencyCode = ConfigurationManager.AppSettings["BaseCurrencyCode"];
org.BaseCurrencyName = ConfigurationManager.AppSettings["BaseCurrencyName"];
org.BaseCurrencySymbol = ConfigurationManager.AppSettings["BaseCurrencySymbol"];

CreateRequest request = new CreateRequest();
request.Entity = org;

CrmDeploymentService crmDeployService = new CrmDeploymentService();
crmDeployService.Credentials = System.Net.CredentialCache.DefaultCredentials;

try
{
crmDeployService.Execute(request);
}
catch (SoapException se)
{
lblError.Text = String.Format("Creation of Organization failed with error:<br>{0}<br>Detail:<br>{1}", se.Message, se.Detail.InnerText);
}
catch (Exception ex)
{
lblError.Text = String.Format("Creation of Organization failed with error:<br>{0}", ex.Message);
}

When you don't want to use the default credentials, then you would supply the username and password like this:

crmDeployService.Credentials = new System.Net.NetworkCredential("administrator", "pass@word1", "litwareinc");

In some cases this might lead to a 401 Unauthorized error message though. This has to do with kerberos. When you do force your application to use NTLM though, then it works. You can do this by using this code:

CredentialCache credential = new System.Net.CredentialCache();
NetworkCredential netCred = new NetworkCredential("administrator", "pass@word1", "litwareinc");
credential.Add(new Uri("http://localhost:5555"), "NTLM", netCred);
crmDeployService.Credentials = credential;

Some other errors you might run into with their respective answers.

0x8004b001 Create new Organization (Name=orgname, Id=10d59133-ae34-de11-a5a9-0003ffab19fc) failed with Exception: System.Security.SecurityException: Requested registry access is not allowed.

This error occurs because the identity of the application pool which is used by Dynamics CRM has no rights to update the records in the registry hyve HKLM\Software\Microsoft\MSCRM. By default this is set to "Network Service". To get rid of the error, open the registry editor (regedit), browse to the MSCRM hyve, rightclick on the hyve and choose "Permissions". You can then give the correct user rights for updating the values.

Most likely you will now run into this error message:

Server was unable to process request.
Detail:
0x8004b001 Create new Organization (Name=orgname,
Id=2015e8d7-b434-de11-a5a9-000b2924ac91) failed with Exception: System.NullReferenceException: Object reference not set to an instance of an
object.

This message does show up because you are working with the Network Service as the Identity for the Application Pool. You should change the identity of the CrmAppPool (see my other blog post). Then do an iisreset and you should get passed this error message.

Do you run into this error message?

Server was unable to process request.
Detail:
0x8004b001 Create new Organization (Name=orgname, Id=2015e8d7-b434-de11-a5a9-0003ffab19fc) failed with Exception: Microsoft.Crm.CrmException: Invalid user auth.

Then you most likely have forgot to do an iisreset. Try that or even a complete server reboot.

Now your provisioning should be starting, but it won't finish due to this error message:

The operation has timed out

Creating a organization can take quite some time. The timeout should be increased so that the creation of the organization can finish successfully before the timeout has expired. Adding this line of code would help:

crmDeployService.Timeout = 6000000;


That should solve your issues regarding the automatically provisioning of organizations for Dynamics CRM.

There could be ofcourse many other issues like out of memory exceptions, but that you can 'easily' solve by adding memory. If you find any other issues with the respective solutions to this topic, please add them to the comments!

10 comments:

DoctaJonez said...

Thanks Ronald, great post as usual! :)

This was very helpful, especially the tip about the 401 Unauthorized error.

Thanks for your really great posts, they've helped me a lot of times :) I've been working with CRM since CRM 3.0, and have been reading your blog for almost 2 years now. I thought I'd post and tell you how grateful I am :)

Thanks,

DoctaJonez of Guardian Force

Ronald Lemmen said...

Thanks Jones,

This feedback keeps me motivated to continue blogging :)

Anonymous said...

Hi Ronald,

Thank you for this useful information.
However, it does not solve the timeout problem. I set the timeout to a very high level, but still the system generates the timeout error.
I checked it with Wireshark and the error appears to come after 307 seconds, roughly 5 minutes.

Is there anything else that one should change.

Thanks in advance.

EV from Leuven

Larry said...

Thanks for the sharing, not only this one, but alos previous ones I have read, and learnt. Very helpful.

Anonymous said...

Hi,

I tried creating one new organization through netowrk credentials using the code mentioned in your blog.I am getting the 'registry' error.I went to regedit and given appropriate permissions for MSCRM key but no use.I am running the code through console application hosted in another place other than the crm server one.Please suggets if anything i am missing.

Ronald Lemmen said...

Hi,

Are you sure that you have selected both read AND write rights on the correct hyve? If so, then it must be that you need to give another user the rights. For test purposes you can give 'everyone' read AND write rights. If that works, remove those rights and figure out which user is used to access the registry.

Good luck!

Anonymous said...

Hi,

I am running the application in the server where crm is intalled and intialising the deployment service using the administrator credentials.The administrator is given read and write permissions in the registry for crm.Still i am getting the same registry error.Given belwo si the code used to intialse credentials for the service.Please let me know if i am still missing anywhere.

CrmDeploymentService crmDeployService = new CrmDeploymentService();
crmDeployService.UseDefaultCredentials = false;
crmDeployService.Credentials = new System.Net.NetworkCredential(userName, password, domain);

Thanks

Ronald Lemmen said...

Have you tried assigning 'everyone' read and write access to the mscrm registry hyve?

Unknown said...

Great post, especially I have encountered the errors in the same order you have specified. Although you forgot to mention modifying Service principal names for CRM website, it made the website inaccessible, from the crm and mps servers, after changing the app pool ID from network service.

Anonymous said...

hi Ronald Great post!

but i still having problems with the 401 unauthorized error even when i use your advice with the NTLM.

When i take a look at the server logs i can see that my request has a succeeded logon.

do you think there's another solutions for this problem?

or maybe i'm the one that doing something wrong?

public CrmDeploymentService.CrmDeploymentService CreateCrmDeploymentService(string userName, string password, string domain)
{
CredentialCache credential = new CredentialCache();
NetworkCredential netCred = new NetworkCredential(userName, password, domain);
credential.Add(new Uri("http://:5555"), "NTLM", netCred);

CrmDeploymentService.CrmDeploymentService crmDeploymentService = new CrmDeploymentService.CrmDeploymentService();
//crmDeploymentService.Credentials = new System.Net.NetworkCredential(userName, password, domain);
crmDeploymentService.Credentials = credential;

return crmDeploymentService;
}

when i try to execute a request from this service i get the error.

thanks in advance :)