Introduction
Lately I have been writing a lot of code to integrate several systems with MS CRM Online 2011. The code snippets in this article will make your life a lot easier. This code has been well tested and does not use any deprecated APIs.
Background
MS CRM Online 2011 is a terrific product from Microsoft, it enables you to quickly create a fully integrated system for your organization. It scales very well in line with your organization's needs.
Microsoft Dynamics CRM Online Prerequisites
- Download the Microsoft Dynamics CRM SDK.
- You must be able to sign in to Microsoft Dynamics CRM Online
- Microsoft Visual Studio 2010
- Microsoft .NET Framework 4 or .NET 4.5
- Install Windows Identity Foundation if using .NET Framework 4; Pre-installed in .NET Framework 4.5
SDK Library references
All the code used in this article references microsoft.xrm.sdk.dll, which can be found in the bin directory after installing the CRM SDK.
Connecting to CRM Online via C# code
This code snippet can be used to connect to CRM online and create a new Entity
. This code also handles duplicate detection via the exception code.
public void Create(Zenbus.IT.ControlCenter.CoreData.BTS.Message message)
{
ClientCredentials Credentials = new ClientCredentials();
Credentials.UserName.UserName = CoreData.BTS.ExternalConfiguration.CrmOnlineUserName;
Credentials.UserName.Password = CoreData.BTS.ExternalConfiguration.CrmOnlinePassword;
Uri OrganizationUri = new Uri(string.Format(@"https://{0}{1}/XRMServices/2011/Organization.svc",
CoreData.BTS.ExternalConfiguration.OrgName, CoreData.BTS.ExternalConfiguration.ServerName));
Uri HomeRealmUri = null;
using (OrganizationServiceProxy serviceProxy =
new OrganizationServiceProxy(OrganizationUri, HomeRealmUri, Credentials, null))
{
CreateRequest request = new CreateRequest();
request.Target = CRMObjectMapper.CRMMessage(message);
request.Parameters["SuppressDuplicateDetection"] = false;
try
{
serviceProxy.Execute(request);
System.Diagnostics.Debug.Write(string.Format("Added new : {0}",
request.Target.LogicalName), EVENT_CATEGORY);
}
catch (FaultException<OrganizationServiceFault> fault)
{
if (fault.Detail.ErrorCode == -2147220685)
{
System.Diagnostics.Debug.Write("Duplicate detected. Reason: " +
fault.Reason.ToString(), EVENT_CATEGORY);
}
else
{
throw;
}
}
}
System.Diagnostics.Debug.Write("Create() complete.", EVENT_CATEGORY);
}
This line of code CRMObjectMapper.CRMMessage(message);
returns an Entity
object. This is how a CRM Entity
can be created using the late binding syntax.
public static Entity CRMMessage(Zenbus.IT.ControlCenter.CoreData.BTS.Message messageInstanceData)
{
Entity entityInstance = new Entity("zen_message");
entityInstance["zen_name"] = messageInstanceData.MessageID;
entityInstance["zen_messagepartcount"] = Int32.Parse(messageInstanceData.MessagePartCount);
entityInstance["zen_messageretrycount"] = Int32.Parse(messageInstanceData.MessageRetryCount);
return entityInstance;
}
Fetching the Entity ID of a newly created Entity
This code snippet can be used to retrieve the Entity
ID GUID for a newly created Entity
or an existing one. Notice the QueryExpression
, you might have to change it to suit your requirement.
public static Guid GetEntityID(string entityName,
string columnName, string columnValue, string guidColumnName)
{
ClientCredentials Credentials = new ClientCredentials();
Credentials.UserName.UserName = CoreData.BTS.ExternalConfiguration.CrmOnlineUserName;
Credentials.UserName.Password = CoreData.BTS.ExternalConfiguration.CrmOnlinePassword;
Uri OrganizationUri = new Uri(string.Format(
@"https://{0}{1}/XRMServices/2011/Organization.svc",
CoreData.BTS.ExternalConfiguration.OrgName, CoreData.BTS.ExternalConfiguration.ServerName));
Uri HomeRealmUri = null;
using (OrganizationServiceProxy serviceProxy =
new OrganizationServiceProxy(OrganizationUri, HomeRealmUri, Credentials, null))
{
QueryExpression query = new QueryExpression()
{
EntityName = entityName,
ColumnSet = new ColumnSet(guidColumnName),
TopCount = 1,
Criteria =
{
Conditions =
{
new ConditionExpression (columnName, ConditionOperator.Equal, columnValue)
}
}
};
DataCollection<Entity> entityCollection = serviceProxy.RetrieveMultiple(query).Entities;
if (entityCollection.Count > 0)
{
return entityCollection[0].Id;
}
else
{
System.Diagnostics.Debug.Write(string.Format(
@"GUID NOT found for entity: {0}, value: {1}, column:{2}, ",
entityName, columnValue, columnName), EVENT_CATEGORY);
return System.Guid.Empty;
}
}
}
Getting CRM OptionSet text by value
In several cases you might want to get the OptionSet
text, given a value. The code snippet below helps you to get it.
public static string GetOptionSetTextByValue(
string entityName, string attributeName, int selectedValue)
{
ClientCredentials Credentials = new ClientCredentials();
Credentials.UserName.UserName = CoreData.BTS.ExternalConfiguration.CrmOnlineUserName;
Credentials.UserName.Password = CoreData.BTS.ExternalConfiguration.CrmOnlinePassword;
Uri OrganizationUri = new Uri(string.Format(
@"https://{0}{1}/XRMServices/2011/Organization.svc",
CoreData.BTS.ExternalConfiguration.OrgName, CoreData.BTS.ExternalConfiguration.ServerName));
Uri HomeRealmUri = null;
using (OrganizationServiceProxy serviceProxy =
new OrganizationServiceProxy(OrganizationUri, HomeRealmUri, Credentials, null))
{
RetrieveAttributeRequest retrieveAttributeRequest = new RetrieveAttributeRequest
{
EntityLogicalName = entityName,
LogicalName = attributeName,
RetrieveAsIfPublished = true
};
RetrieveAttributeResponse retrieveAttributeResponse =
(RetrieveAttributeResponse) serviceProxy.Execute(retrieveAttributeRequest);
Microsoft.Xrm.Sdk.Metadata.PicklistAttributeMetadata
retrievedPicklistAttributeMetadata = (Microsoft.Xrm.Sdk.Metadata.PicklistAttributeMetadata)
retrieveAttributeResponse.AttributeMetadata;
OptionMetadata[] optionList = retrievedPicklistAttributeMetadata.OptionSet.Options.ToArray();
string selectedOptionLabel = string.Empty;
foreach (OptionMetadata omd in optionList)
{
if (omd.Value == selectedValue)
{
selectedOptionLabel = omd.Label.UserLocalizedLabel.Label;
break;
}
}
return selectedOptionLabel;
}
}
How to associate N-N relationship via the SDK
The code snippet below helps you to associate an N-to-N relationship between Entity
s via the CRM SDK code.
public static bool Associate_N2N_EntityRecords(
Microsoft.Xrm.Sdk.EntityReference parentReference,
Microsoft.Xrm.Sdk.EntityReference childReference, string relationshipName)
{
ClientCredentials Credentials = new ClientCredentials();
Credentials.UserName.UserName = CoreData.BTS.ExternalConfiguration.CrmOnlineUserName;
Credentials.UserName.Password = CoreData.BTS.ExternalConfiguration.CrmOnlinePassword;
Uri OrganizationUri = new Uri(string.Format(
@"https://{0}{1}/XRMServices/2011/Organization.svc",
CoreData.BTS.ExternalConfiguration.OrgName, CoreData.BTS.ExternalConfiguration.ServerName));
Uri HomeRealmUri = null;
using (OrganizationServiceProxy serviceProxy =
new OrganizationServiceProxy(OrganizationUri, HomeRealmUri, Credentials, null))
{
AssociateRequest associateRequest = new AssociateRequest
{
Target = new EntityReference(parentReference.LogicalName, parentReference.Id),
RelatedEntities = new EntityReferenceCollection
{
new EntityReference(childReference.LogicalName, childReference.Id)
},
Relationship = new Relationship(relationshipName)
};
serviceProxy.Execute(associateRequest);
}
return true;
}
How to quickly add Annotations to your Entity
The code snippet below helps you to quickly add Annotations. Note that this code returns an annotation Entity
object.
public static Entity CRMOrchestrationAnnotation(EntityReference parentReference, string orchestrationImagePath)
{
FileInfo fileInfo = new FileInfo(orchestrationImagePath);
byte[] imageArray = new byte[fileInfo.Length];
var fileStream = fileInfo.OpenRead();
fileStream.Read(imageArray, 0, (int)fileInfo.Length - 1);
Entity entityInstance = new Entity("annotation");
entityInstance["filename"] = fileInfo.Name;
entityInstance["mimetype"] = @"image/jpeg";
entityInstance["documentbody"] = Convert.ToBase64String(imageArray);
entityInstance["objectid"] = parentReference;
entityInstance["subject"] = "Orchestration Image";
entityInstance["notetext"] = String.Format("{0:F}", DateTime.Now);
return entityInstance;
}
How to update an existing Entity in CRM
This code snippet helps to update an existing Entity
. If the Entity
is not found, it creates it.
public void Update(Zenbus.IT.ControlCenter.CoreData.BTS.Orchestration artifact)
{
ClientCredentials Credentials = new ClientCredentials();
Credentials.UserName.UserName = CoreData.BTS.ExternalConfiguration.CrmOnlineUserName;
Credentials.UserName.Password = CoreData.BTS.ExternalConfiguration.CrmOnlinePassword;
Uri OrganizationUri = new Uri(string.Format(
@"https://{0}{1}/XRMServices/2011/Organization.svc",
CoreData.BTS.ExternalConfiguration.OrgName, CoreData.BTS.ExternalConfiguration.ServerName));
Uri HomeRealmUri = null;
using (OrganizationServiceProxy serviceProxy =
new OrganizationServiceProxy(OrganizationUri, HomeRealmUri, Credentials, null))
{
try
{
Entity updatedEntity = CRMObjectMapper.CRMOrchestration(artifact);
updatedEntity.Id = CRMBase.GetEntityID("zen_orchestration",
"zen_name", artifact.Name, "zen_orchestrationid");
if (!updatedEntity.Id.Equals(Guid.Empty))
{
UpdateRequest request = new UpdateRequest();
request.Target = updatedEntity;
serviceProxy.Execute(request);
System.Diagnostics.Debug.Write(string.Format("Updated : {0}",
request.Target.LogicalName), EVENT_CATEGORY);
}
else {
System.Diagnostics.Debug.Write(string.Format(
"Create initiated, as record does NOT exist : {0}",
artifact.Name), EVENT_CATEGORY);
List<Zenbus.IT.ControlCenter.CoreData.BTS.Orchestration> list =
new List<CoreData.BTS.Orchestration>();
list.Add(artifact);
this.Create(list);
}
}
catch (FaultException<OrganizationServiceFault> fault)
{
if (fault.Detail.ErrorCode == -2147220685)
{
System.Diagnostics.Debug.Write("Duplicate detected. Reason: " +
fault.Reason.ToString(), EVENT_CATEGORY);
}
else
{
throw;
}
}
}
System.Diagnostics.Debug.Write("Update() complete.", EVENT_CATEGORY);
}
How to quickly create an OptionSet in CRM?
This code snippet helps you to populate an OptionSet
in CRM.
private static OptionSetValue CreateOptionSet(int optionSetValue)
{
OptionSetValue optionSetInstance = new OptionSetValue();
optionSetInstance.Value = optionSetValue;
return optionSetInstance;
}
CreateOptionSet()
usage, while creating an Entity
:
entityInstance.Attributes["zen_direction"] = CreateOptionSet(100000001);
Source code references
After installing the CRM SDK, you might also want to check out the samplecode/cs/helpercode directory for additional source code.
Takeaways
It is recommended that you build a C# library to handle most of the scenarios in a CRM integration, this shall help you to code quickly.