One of the new features in the Dynamics CRM 2013 SDK is the ability to execute operations asynchronously. At the moment this feature is limited to only solution imports.
Previously in Dynamics CRM 2011 you were only able to import solutions synchronously. This means that the caller had to wait until the solution import process completes. This resulted in time out errors when importing large or complex solutions. Customers had to increase their time out settings significantly for on-premise deployments. For CRM online, the only option was to catch the exception and do some queries to figure out if the solution import was actually successful or no.
In Dynamics CRM 2013, the “ExecuteAsync” message solves this problem. All we have to do is submit a request to the Dynamics CRM Organization Service using this message. The message would kick off a server side process asynchronously to process the request and return the id of the server side process immediately to the caller. The caller then can query the status of the server side process to figure out if the request was processed correctly.
Take a look at the example below. This method supports both synchronous and asynchronous imports. For asynchronous imports, it can optionally wait for the import job to finish and report on the status.
- public Guid? Import(string solutionFilePath,
- bool publishWorkflows,
- bool convertToManaged,
- bool overwriteUnmanagedCustomizations,
- bool importAsync,
- bool waitForCompletion,
- int sleepInterval,
- int asyncWaitTimeout)
- {
- Guid? asyncJobId = null;
- byte[] solutionBytes = File.ReadAllBytes(solutionFilePath);
- ImportSolutionRequest importSolutionRequest = newImportSolutionRequest()
- {
- CustomizationFile = solutionBytes,
- PublishWorkflows = publishWorkflows,
- ConvertToManaged = convertToManaged,
- OverwriteUnmanagedCustomizations = overwriteUnmanagedCustomizations
- };
- if (importAsync)
- {
- ExecuteAsyncRequest asyncRequest = newExecuteAsyncRequest()
- {
- Request = importSolutionRequest
- };
- ExecuteAsyncResponse asyncResponse = OrgService.Execute(asyncRequest) asExecuteAsyncResponse;
- asyncJobId = asyncResponse.AsyncJobId;
- if (waitForCompletion)
- {
- DateTime end = DateTime.Now.AddSeconds(asyncWaitTimeout);
- while (end >= DateTime.Now)
- {
- AsyncOperation asyncOperation = OrgService.Retrieve(“asyncoperation”, asyncJobId.Value,
- newColumnSet(“asyncoperationid”, “statuscode”, “message”)).ToEntity < AsyncOperation>();
- switch (asyncOperation.StatusCode.Value)
- {
- //Succeeded
- case 30:
- return asyncJobId;
- //Pausing //Canceling //Failed //Canceled
- case 21:
- case 22:
- case 31:
- case 32:
- thrownewException(string.Format(“Solution Import Failed: {0} {1}”,
- asyncOperation.StatusCode.Value, asyncOperation.Message));
- default:
- break;
- }
- }
- thrownewException(string.Format(“Import Timeout: {0}”, asyncWaitTimeout));
- }
- return asyncJobId;
- }
- else
- {
- ImportSolutionResponse importSolutionResponse = OrgService.Execute(importSolutionRequest) asImportSolutionResponse;
- }
- return asyncJobId;
- }
You can start using this feature immediately by downloading the xRM CI Toolkit. This will provide you with a PowerShell Cmdlet to do exactly the above. See an example on how to use this below. This script invokes the solution import asynchronously and waits until the import completes.
- Import-Module “C:\Program Files (x86)\Xrm CI Framework\CRM 2013\PowerShell Cmdlets\Xrm.Framework.CI.PowerShell.dll”
- $connection = “ServiceUri=http://appserver.cloudapp.net:5555/Sample/XRMServices/2011/Organization.svc; Domain=XRM; UserName=Wael; Password=******”
- Import-XrmSolution -ConnectionString $connection -SolutionFilePath “C:\Sample.zip” -PublishWorkflows $true -ConvertToManaged $false -OverwriteUnmanagedCustomizations $true ImportAsync $true -WaitForCompletion $true
Check my previous post to learn more about the xRM CI Framework and how you can use it in your projects.
