Call External Cross Domain REST API/SOAP Service from CRM Plugins/Custom Workflows.

In Dynamics 365, if you have any requirement to call cross domain REST API/SOAP UI, we can’t directly call from JavaScript, we need to create a custom workflow and create CRM action on top of it. These CRM Actions can be called from anywhere.

For REST API, it is very simple, crate a custom workflow with following code, and call this custom workflow from any CRM Action. This can be used in Plugins also.

 public string CallRESTAPIService(string restAPIURL, string serviceCredentials)
        {
            string jsonResponse = string.Empty;
            var uri = new Uri(restAPIURL);
            var request = WebRequest.Create(uri);
            request.Method = WebRequestMethods.Http.Get;
            request.ContentType = "application/json";
            request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(serviceCredentials));
            try
            {
                using (var response = request.GetResponse())
                {
                    using (var reader = new StreamReader(response.GetResponseStream()))
                    {
                        jsonResponse = reader.ReadToEnd();
                    }
                }
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
            return jsonResponse;
        }

For SOAP Service, if you have requirement to call within plugin it is simple. If you want to call from JavaScript, you have to convert request and response into JSON format. First you have to convert JSON Request into C# Object and then C# Object Response to JSON Response. There are two options;
• Newtonsoft.Json Nuget library. If you are using, you need to always merge your custom workflow/plugin DLL
• DataContractJsonSerializer- System.Runtime.Serialization assembly should be added to use this. No need to merge the DLL.

 public SOAPServiceRequest DeSerializeJSONRequestToObject(string requestJSON)
        {
            SOAPServiceRequest deserializedRequest = new SOAPServiceRequest();
            MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(requestJSON));
            DataContractJsonSerializer ser = new DataContractJsonSerializer(deserializedRequest.GetType());
            deserializedRequest = ser.ReadObject(ms) as SOAPServiceRequest;
            ms.Close();
            return deserializedRequest;
        }

        public string SerializeResponseObjectToJSON(SOAPServiceResponse reponse)
        {
            string strJSON = string.Empty;
            using (MemoryStream SerializememoryStream = new MemoryStream())
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(SOAPServiceResponse));
                serializer.WriteObject(SerializememoryStream, reponse);
                SerializememoryStream.Position = 0;
                StreamReader sr = new StreamReader(SerializememoryStream);
                strJSON = sr.ReadToEnd();
            }
            return strJSON;
        }

        public SOAPServiceResponse CallAddressValidation(ITracingService tracingService, string serviceURL, string serviceUserName, string servicePassword, string crmUserName, string addressLine, string city, string state, string postalCode)
        {
            BasicHttpsBinding binding = new BasicHttpsBinding();
            EndpointAddress address = new EndpointAddress(serviceURL);
            ServiceSoapClient soapClient = new ServiceSoapClient(binding, address);
            soapClient.ClientCredentials.UserName.UserName = serviceUserName;
            soapClient.ClientCredentials.UserName.Password = servicePassword;
            SOAPServiceRequest requestType = new SOAPServiceRequest();    
            using (OperationContextScope scope = new OperationContextScope(soapClient.InnerChannel))
            {
                HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
                httpRequestProperty.Headers[HttpRequestHeader.Authorization] = "Basic " +
                Convert.ToBase64String(Encoding.ASCII.GetBytes(soapClient.ClientCredentials.UserName.UserName + ":" +
                soapClient.ClientCredentials.UserName.Password));
                OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
               //
               //Pass request data
               //
               var serviceResponse = soapClient.ValidateService(requestType);
                return serviceResponse;
            }            
        }

Re-assign Account/User territory in Dynamics CRM 2011

Unfortunately Dynamics CRM 2011 does not support deactivating Territory, If you get a situation where you want to delete the existing territory, you need to first check if it is associated to any accounts or users, if the territory has salespeople(users) or accounts associated with it, the deletion will not succeed, Territory entity have 1:N relationships with “Referential, Restrict Delete” behavior on Account and User, Users cannot directly delete a territory, If the Territory has Users or Accounts associated with it, In order to delete the Territory, need to reassign associated Users and Accounts to different Territory.

Following code helps to re-assign accounts and users territory from one territory to another one.

 private void ReAssignAccountTerritories(IOrganizationService service, string oldTerritoryName, string newTerritoryName)
        {
            try
            {
                string accountsFetchXML = string.Format(@"<fetch version='1.0' output-format='xml-platform' mapping='logical' no-lock='true' distinct='false'>
                                                            <entity name='account'>
                                                                <attribute name='accountid' />
                                                                <attribute name='name' />
                                                                <link-entity name='territory' from='territoryid' to='territoryid' alias='aa'>
                                                                    <filter type='and'>
                                                                        <condition attribute='name' operator='eq' value='{0}' />
                                                                    </filter>
                                                                </link-entity>
                                                            </entity>
                                                        </fetch>", oldTerritoryName);

                var accountsFetchExp = new FetchExpression(accountsFetchXML);

                //Get Accounts with Old Territory
                EntityCollection accountsResults = service.RetrieveMultiple(accountsFetchExp);

                string territoryFetchXML = string.Format(@"<fetch version='1.0' output-format='xml-platform' mapping='logical' no-lock='true' distinct='false'>
                                                            <entity name='territory'>
                                                                <attribute name='territoryid' />
                                                                <filter type='and'>
                                                                    <condition attribute='name' operator='eq' value='{0}' />
                                                                </filter>
                                                            </entity>
                                                        </fetch>", newTerritoryName);

                var territoryFetchExp = new FetchExpression(territoryFetchXML);
                //Get TerritoryId based on TerritoryName
                EntityCollection territoryResults = service.RetrieveMultiple(territoryFetchExp);

                EntityReference territoryReference = null;

                if (territoryResults.Entities != null && territoryResults.Entities.Count > 0)
                    territoryReference = new EntityReference("territory", territoryResults.Entities[0].Id);

                foreach (Entity account in accountsResults.Entities)
                {
                    if (territoryReference != null)
                    {
                        //Update Account Territory with new Territory
                        account.Attributes.Add("territoryid", territoryReference);
                        service.Update(account);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void ReAssignUserTerritories(IOrganizationService service, string oldTerritoryName, string newTerritoryName)
        {
            try
            {
                string usersFetchXML = string.Format(@"<fetch version='1.0' output-format='xml-platform' mapping='logical' no-lock='true' distinct='false'>
                                                        <entity name='systemuser'>
                                                            <attribute name='systemuserid' />
                                                            <attribute name='fullname' />
                                                            <link-entity name='territory' from='territoryid' to='territoryid' alias='aa'>
                                                                <filter type='and'>
                                                                    <condition attribute='name' operator='eq' value='{0}' />
                                                                </filter>
                                                            </link-entity>
                                                        </entity>
                                                    </fetch>", oldTerritoryName);

                var usersFetchExp = new FetchExpression(usersFetchXML);

                EntityCollection usersResults;

                //Get Users with Old Territory
                usersResults = service.RetrieveMultiple(usersFetchExp);

                string territoryFetchXML = string.Format(@"<fetch version='1.0' output-format='xml-platform' mapping='logical' no-lock='true' distinct='false'>
                                                            <entity name='territory'>
                                                                <attribute name='territoryid' />
                                                                <filter type='and'>
                                                                    <condition attribute='name' operator='eq' value='{0}' />
                                                                </filter>
                                                            </entity>
                                                        </fetch>", newTerritoryName);

                var territoryFetchExp = new FetchExpression(territoryFetchXML);
                //Get TerritoryId based on TerritoryName
                EntityCollection territoryResults = service.RetrieveMultiple(territoryFetchExp);

                EntityReference territoryReference = null;

                if (territoryResults.Entities != null && territoryResults.Entities.Count > 0)
                    territoryReference = new EntityReference("territory", territoryResults.Entities[0].Id);

                foreach (Entity user in usersResults.Entities)
                {
                    if (territoryReference != null)
                    {
                        //Update User Territory with new Territory
                        user.Attributes.Add("territoryid", territoryReference);
                        service.Update(user);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

There are still open activities associated with this case, when resolving/cancelling a Case in Dynamics CRM 2011

Problem:
When you try to resolve a case in Dynamics CRM 2011, which has open activities of Task, E-mail, Phone Call, Letter, Fax, Appointment and Service Activity you will get following error message “There are still open activities associated with this case, these must be closed before the case can be closed.”

Case_Open_Activities_Message

If you are trying to cancel a case which has open activities, you will get following error message.

Cancel_Case

If you are trying to resolve a case thru CRM SDK code, you will get following error message “The incident can not be cancelled because there are open activities for this incident.”

Case_Open_Activities_ErrorMessage

Solution 1:
If you are resolving a Case from CRM UI, you need to manually open each associated activity of the case and do ‘Mark Complete’ or ‘Cancel’
Solution 2:
If you are resolving a case from CRM SDK, you need to use following code to cancel all associated activities of the case.


  // Cancel all associated Case activities which are Open and Scheduled
        public static void CancelCaseActivities(IOrganizationService orgService, Guid caseId)
        {
            string fetchXML = string.Format(@"<fetch version='1.0' output-format='xml-platform' mapping='logical' no-lock='true' distinct='false'>
                                                    <entity name='activitypointer'>
                                                        <attribute name='activityid' />
                                                        <attribute name='activitytypecode' />
                                                        <filter type='and'>
                                                            <condition attribute='regardingobjectid' operator='eq' value='{0}' />
                                                            <condition attribute='statecode' operator='in'>
                                                                <value>0</value>
                                                                <value>3</value>
                                                            </condition>
                                                        </filter>
                                                    </entity>
                                              </fetch>", caseId.ToString());

            var fetchExp = new FetchExpression(fetchXML);

            var activities = orgService.RetrieveMultiple(fetchExp);

            foreach (Entity activity in activities.Entities)
            {
                CancelActivity(activity, orgService);
            }
        }

        // Cancel an Activity
        private static void CancelActivity(Entity entity, IOrganizationService service)
        {
            EntityReference moniker = new EntityReference();
            if (entity.LogicalName == "activitypointer")
            {
                if (entity.Attributes.Contains("activityid") & entity.Attributes.Contains("activitytypecode"))
                {
                    moniker.LogicalName = entity.Attributes["activitytypecode"].ToString();
                    moniker.Id = (Guid)entity.Attributes["activityid"];
                    SetStateRequest request = new SetStateRequest();
                    request.EntityMoniker = moniker;
                    request.State = new OptionSetValue(2);
                    request.Status = new OptionSetValue(-1);
                    SetStateResponse response = (SetStateResponse)service.Execute(request);
                }
            }
        }

Merge warning: sub-entity might lose parenting in Dynamics CRM 2011

Problem:
If you are trying to merge two accounts, If master account record does not have a parent account, but the subordinate account record does, then you will get following warning message if you do Merge from CRM UI otherwise if you do Merge from SDK code using MergeRequest class you will get an exception saying that “Exception Message: Merge warning: sub-entity might lose parenting”

Merge Warning

Solution:

If you are doing Merge from CRM UI, after you get above warning message, click on “OK” button to continue the merge.
If you are doing Merge from SDK code using MergeRequest class, you should specify PerformParentingChecks property to false. This property used to check if the parent information is different for the two entity records. If it is true it will check the parent information is different for the two entity records.

Sample code is here:

 // Merge Accounts
        public void MergeAccounts(Guid masterAccountId, Guid subOrdinateAccountId)
        {
            try
            {
                //Create CRM Connection        
                IOrganizationService crmConnection = GetCRMConnection();

                //Create the target for the request.        
                EntityReference target = new EntityReference();

                //Id is the GUID of the account that is being merged into.        
                //LogicalName is the type of the entity being merged to, as a string        
                target.Id = masterAccountId;
                target.LogicalName = "account";

                //Create the request.        
                MergeRequest merge = new MergeRequest();

                // SubordinateId is the GUID of the account merging.    
                merge.SubordinateId = subOrdinateAccountId;
                merge.Target = target;
                merge.PerformParentingChecks = false;
                Entity updateContent = new Entity("account");
                var cols = new ColumnSet(new[] { "primarycontactid", "websiteurl", "telephone1", "fax", "emailaddress1" });

                //Get Master Account Primary Contact,Website,Phone,Fax,Email
                var masterAccount = crmConnection.Retrieve("account", masterAccountId, cols);

                //Get Subordinate Account Primary Contact,Website,Phone,Fax,Email
                var subOrdinateAccount = crmConnection.Retrieve("account", subOrdinateAccountId, cols);

                //If PrimaryContact,Website,Phone,Fax,Email fields data are populated on the Subordinate Account and NOT populated on the Master Account. updated these Subordinate account values to the Master record.                  
                if (!masterAccount.Contains("primarycontactid") && subOrdinateAccount.Contains("primarycontactid"))
                    updateContent.Attributes.Add("primarycontactid", new EntityReference("contact", subOrdinateAccount.GetAttributeValue<EntityReference>("primarycontactid").Id));

                if (!masterAccount.Contains("websiteurl") && subOrdinateAccount.Contains("websiteurl"))
                    updateContent.Attributes.Add("websiteurl", subOrdinateAccount.Attributes["websiteurl"]);

                if (!masterAccount.Contains("telephone1") && subOrdinateAccount.Contains("telephone1"))
                    updateContent.Attributes.Add("telephone1", subOrdinateAccount.Attributes["telephone1"]);

                if (!masterAccount.Contains("fax") && subOrdinateAccount.Contains("fax"))
                    updateContent.Attributes.Add("fax", subOrdinateAccount.Attributes["fax"]);

                if (!masterAccount.Contains("emailaddress1") && subOrdinateAccount.Contains("emailaddress1"))
                    updateContent.Attributes.Add("emailaddress1", subOrdinateAccount.Attributes["emailaddress1"]);

                merge.UpdateContent = updateContent;

                // Execute the request.   
                MergeResponse mergeRes = (MergeResponse)crmConnection.Execute(merge);
            }
            catch (Exception ex)
            {
                //Throw the exception        
                throw ex;
            }
        }

Use ExecuteMultipleRequest for bulk Create/Update/Delete using C# in Dynamics CRM 2011

Using this we can create/update/delete bunch of records at a time. It avoids calling OrgService.Create or Update or Delete every time.

This has been added to the Microsoft Dynamics CRM 2011 Update Rollup 12, it is available from SDK 5.0.13. Here is reference MSDN URL http://msdn.microsoft.com/en-us/library/jj863631.aspx

Default max batch size is 1000, that means Using this you can create/update/delete up to 1000 records only at a time.

Here are sample code blocks for bulk Create, Update and Delete

 


     /// <summary>
        /// Call this method for bulk Create
        /// </summary>
        /// <param name="service">Org Service</param>
        /// <param name="entities">Collection of entities to Create</param>
        public static void BulkCreate(IOrganizationService service, DataCollection<Entity> entities)
        {
            // Create an ExecuteMultipleRequest object.
            var multipleRequest = new ExecuteMultipleRequest()
            {
                // Assign settings that define execution behavior: continue on error, return responses. 
                Settings = new ExecuteMultipleSettings()
                {
                    ContinueOnError = false,
                    ReturnResponses = true
                },
                // Create an empty organization request collection.
                Requests = new OrganizationRequestCollection()
            };

            // Add a CreateRequest for each entity to the request collection.
            foreach (var entity in entities)
            {
                CreateRequest createRequest = new CreateRequest { Target = entity };
                multipleRequest.Requests.Add(createRequest);
            }

            // Execute all the requests in the request collection using a single web method call.
            ExecuteMultipleResponse multipleResponse = (ExecuteMultipleResponse)service.Execute(multipleRequest);

        }

        /// <summary>
        /// Call this method for bulk update
        /// </summary>
        /// <param name="service">Org Service</param>
        /// <param name="entities">Collection of entities to Update</param>
        public static void BulkUpdate(IOrganizationService service, DataCollection<Entity> entities)
        {
            // Create an ExecuteMultipleRequest object.
            var multipleRequest = new ExecuteMultipleRequest()
            {
                // Assign settings that define execution behavior: continue on error, return responses. 
                Settings = new ExecuteMultipleSettings()
                {
                    ContinueOnError = false,
                    ReturnResponses = true
                },
                // Create an empty organization request collection.
                Requests = new OrganizationRequestCollection()
            };

            // Add a UpdateRequest for each entity to the request collection.
            foreach (var entity in entities)
            {
                UpdateRequest updateRequest = new UpdateRequest { Target = entity };
                multipleRequest.Requests.Add(updateRequest);
            }

            // Execute all the requests in the request collection using a single web method call.
            ExecuteMultipleResponse multipleResponse = (ExecuteMultipleResponse)service.Execute(multipleRequest);

        }

        /// <summary>
        /// Call this method for bulk delete
        /// </summary>
        /// <param name="service">Org Service</param>
        /// <param name="entityReferences">Collection of EntityReferences to Delete</param>
        public static void BulkDelete(IOrganizationService service, DataCollection<EntityReference> entityReferences)
        {
            // Create an ExecuteMultipleRequest object.
            var multipleRequest = new ExecuteMultipleRequest()
            {
                // Assign settings that define execution behavior: continue on error, return responses. 
                Settings = new ExecuteMultipleSettings()
                {
                    ContinueOnError = false,
                    ReturnResponses = true
                },
                // Create an empty organization request collection.
                Requests = new OrganizationRequestCollection()
            };

            // Add a DeleteRequest for each entity to the request collection.
            foreach (var entityRef in entityReferences)
            {
                DeleteRequest deleteRequest = new DeleteRequest { Target = entityRef };
                multipleRequest.Requests.Add(deleteRequest);
            }

            // Execute all the requests in the request collection using a single web method call.
            ExecuteMultipleResponse multipleResponse = (ExecuteMultipleResponse)service.Execute(multipleRequest);
        }

Fetch XML and ConditionExpression operators using C# in Dynamics CRM 2011

Following table describes different types of operators we can use in a ConditionExpression and Fetch XML in Dynamics CRM 2011

ConditionOperator FetchXML Operator Description
BeginsWith like The string occurs at the beginning of another string.
Between between The value is between two values.
Contains like The string contains another string.
DoesNotBeginWith not-like The string does not begin with another string.
DoesNotContain not-like The string does not contain another string.
DoesNotEndWith not-like The string does not end with another string.
EndsWith like The string ends with another string.
Equal eq The values are compared for equality.
EqualBusinessId eq-businessid The value is equal to the specified business ID.
EqualUserId eq-userid The value is equal to the specified user ID.
EqualUserTeams eq-userteams The record is owned by teams that the user is a member of.
GreaterEqual ge The value is greater than or equal to the compared value.
GreaterThan gt The value is greater than the compared value.
In in TheThe value exists in a list of values.
InFiscalPeriod in-fiscal-period The value is within the specified fiscal period.
InFiscalPeriodAndYear in-fiscal-period-and-year The value is within the specified fiscal period and year.
InFiscalYear in-fiscal-year The value is within the specified year.
InOrAfterFiscalPeriodAndYear in-or-after-fiscal-period-and-year The value is within or after the specified fiscal period and year.
InOrBeforeFiscalPeriodAndYear in-or-before-fiscal-period-and-year The value is within or before the specified fiscal period and year.
Last7Days last-seven-days The value is within the last seven days including today.
LastFiscalPeriod last-fiscal-period The value is within the last fiscal period.
LastFiscalYear last-fiscal-year The value is within the last fiscal year.
LastMonth last-month The value is within the last month including first day of the last month and last
day of the last month.
LastWeek last-week The value is within the previous week including Sunday through Saturday.
LastXDays last-x-days The value is within last X days.
LastXFiscalPeriods last-x-fiscal-periods The value is within the last X (specified value) fiscal periods.
LastXFiscalYears last-x-fiscal-years The value is within the last X (specified value) fiscal periods.
LastXHours last-x-hours The value is within the last X hours.
LastXMonths last-x-months The value is within the last X (specified value) months.
LastXWeeks last-x-weeks The value is within the last X (specified value) weeks.
LastXYears last-x-years The value is within the last X years.
LastYear last-year The value is within the previous year.
LessEqual le The value is less than or equal to the compared value.
LessThan lt The value is less than the compared value.
Like like The character string is matched to the specified pattern.
Next7Days next-seven-days The value is within the next seven days.
NextFiscalPeriod next-fiscal-period The value is within the next fiscal period.
NextFiscalYear next-fiscal-year The value is within the next fiscal year.
NextMonth next-month The value is within the next month.
NextWeek next-week The value is within the next week.
NextXDays next-x-days The value is within the next X (specified value) days.
NextXFiscalPeriods next-x-fiscal-periods The value is within the next X (specified value) fiscal period.
NextXFiscalYears next-x-fiscal-years The value is within the next X (specified value) fiscal years.
NextXHours next-x-hours The value is within the next X (specified value) hours.
NextXMonths next-x-months The value is within the next X (specified value) months.
NextXWeeks next-x-weeks The value is within the next X weeks.
NextXYears next-x-years The value is within the next X years.
NextYear next-year The value is within the next year.
NotBetween not-between The value is not between two values.
NotEqual ne The two values are not equal.
NotEqualBusinessId ne-businessid The value is not equal to the specified business ID.
NotEqualUserId ne-userid The value is not equal to the specified user ID.
NotIn not-in The given value is not matched to a value in a subquery or a list.
NotLike not-like The character string does not match the specified pattern.
NotNull not-null The value is not null.
NotOn ne The value is not on the specified date.
Null null The value is null.
OlderThanXMonths olderthan-x-months The value is older than the specified number of months.
On on The value is on a specified date.
OnOrAfter on-or-after The value is on or after a specified date.
OnOrBefore on-or-before The value is on or before a specified date.
ThisFiscalPeriod this-fiscal-period The value is within the current fiscal period.
ThisFiscalYear this-fiscal-year The value is within the current fiscal year.
ThisMonth this-month The value is within the current month.
ThisWeek this-week The value is within the current week.
ThisYear this-year The value is within the current year.
Today today The value equals today’s date.
Tomorrow tomorrow The value equals tomorrow’s date.
Yesterday yesterday The value equals yesterday’s date.

Use NoLock and Distinct in Fetch XML and QueryExpression using C# in Dynamics CRM 2011

NoLock: It indicates that no database locks are issued against the data that would prohibit other transactions from modifying the data in the records returned from the query.

Distinct:  It indicates whether results of the query contains duplicate entity instances

Using these in FetchXML and QueryExpression improves performance for checking/fetching results

 


 public static EntityCollection GetAccounts(IOrganizationService service, string accountName)
        {
            QueryExpression queryExp = new QueryExpression();
            queryExp.EntityName = "account";
            var cols = new ColumnSet(new[] { "name", "accountid" });
            queryExp.ColumnSet = cols;

            ConditionExpression conExp = new ConditionExpression();
            conExp.AttributeName = "name";
            conExp.Operator = ConditionOperator.Like;
            conExp.Values.Add(accountName);

            FilterExpression filterExp = new FilterExpression();       
            filterExp.Conditions.Add(conExp);

            queryExp.Criteria = filterExp;
                        
            queryExp.Distinct = false;
            
            queryExp.NoLock = true;

            var accounts = service.RetrieveMultiple(queryExp);

            return accounts;
        }

        public static EntityCollection GetAccounts(IOrganizationService service, string accountName)
        {            
            string fetchXML = string.Format(@"<fetch version='1.0' output-format='xml-platform' mapping='logical' no-lock='true' distinct='false'>
                                                        <entity name='account'>                                                                
                                                            <attribute name='accountid' />
                                                            <attribute name='name' />
                                                            <filter type='and'>
                                                                <condition attribute='name' operator='like' value='{0}' />                                                                                                    
                                                            </filter>
                                                        </entity>
                                                    </fetch>", accountName);

            var fetchExp = new FetchExpression(fetchXML);

            var accounts = service.RetrieveMultiple(fetchExp);

            return accounts;
        }

Get fetch XML link-entity attributes using C# in Dynamics CRM 2011

Following example code shows how to get Account Primary Contact details using fetch XML link-entity

Note: Specify ‘alias’ name different than ‘attributename’ and use same alias name in GetAttributeValue


        //Get Account PrimaryContact details
        public static void GetAccountPrimaryContactDetails(Guid accountId, IOrganizationService orgService)
        {
            var contactFirstName = default(object);
            var contactLastName = default(object);
            var contactFullName = default(object);

            string fetchXML = string.Format(@"<fetch version='1.0' output-format='xml-platform' no-lock='true' mapping='logical'>
                                                <entity name='account'>
                                                    <attribute name='name' />                                                                                
                                                    <filter type='and'>
                                                        <condition attribute='statuscode' operator='eq' value='1' />                                            
                                                        <condition attribute='accountid' operator='eq' value='{0}' />
                                                    </filter>                                        
                                                    <link-entity name='contact' from='contactid' to='primarycontactid' alias='ab'>
                                                         <attribute name='fullname' alias='as_fullname' />
                                                         <attribute name='firstname' alias='as_firstname' />                                             
											             <attribute name='lastname' alias='as_lastname' />
                                                    </link-entity>
                                                </entity>
                                            </fetch>", accountId.ToString());

            var fetchExp = new FetchExpression(fetchXML);

            EntityCollection accountEntity = orgService.RetrieveMultiple(fetchExp);

            if (accountEntity.Entities.Count > 0)
            {
                //Primary Contact Fullname
                AliasedValue avContactFullname = accountEntity.Entities[0].GetAttributeValue<AliasedValue>("as_fullname");
                if (avContactFullname != null)
                    contactFullName = avContactFullname.Value;
                //Primary Contact Firstname
                AliasedValue avContactFirstname = accountEntity.Entities[0].GetAttributeValue<AliasedValue>("as_firstname");
                if (avContactFirstname != null)
                    contactFirstName = avContactFirstname.Value;
                //Primary Contact Lastname
                AliasedValue avContactLastname = accountEntity.Entities[0].GetAttributeValue<AliasedValue>("as_lastname");
                if (avContactLastname != null)
                    contactLastName = avContactLastname.Value;
            }
        }

Activate/Deactivate a record using C# in Dynamics CRM 2011

In Dynamics CRM 2011 every entity has its own StateCode and StatusCode values. Below example code works with Account and Contact entities. For other entities check entity metadata for Statecode and StatusCode values and update the value accordingly.


        //Deactivate a record
        public static void DeactivateRecord(string entityName, Guid recordId, IOrganizationService organizationService)
        {
            var cols = new ColumnSet(new[] { "statecode", "statuscode" });

            //Check if it is Active or not
            var entity = organizationService.Retrieve(entityName, recordId, cols);

            if (entity != null && entity.GetAttributeValue<OptionSetValue>("statecode").Value == 0)
            {
                //StateCode = 1 and StatusCode = 2 for deactivating Account or Contact
                SetStateRequest setStateRequest = new SetStateRequest()
                {
                    EntityMoniker = new EntityReference
                    {
                        Id = recordId,
                        LogicalName = entityName,
                    },
                    State = new OptionSetValue(1),
                    Status = new OptionSetValue(2)
                };
                organizationService.Execute(setStateRequest);
            }
        }

        //Activate a record
        public static void ActivateRecord(string entityName, Guid recordId, IOrganizationService organizationService)
        {
            var cols = new ColumnSet(new[] { "statecode", "statuscode" });

            //Check if it is Inactive or not
            var entity = organizationService.Retrieve(entityName, recordId, cols);

            if (entity != null && entity.GetAttributeValue<OptionSetValue>("statecode").Value == 1)
            {
                //StateCode = 0 and StatusCode = 1 for activating Account or Contact
                SetStateRequest setStateRequest = new SetStateRequest()
                {
                    EntityMoniker = new EntityReference
                    {
                        Id = recordId,
                        LogicalName = entityName,
                    },
                    State = new OptionSetValue(0),
                    Status = new OptionSetValue(1)
                };
                organizationService.Execute(setStateRequest);
            }
        }

Associate and Disassociate Many to Many relationship records using C# in Microsoft Dynamics CRM 2011

If we have any N:N(Many to Many) relationship in Microsoft Dynamics CRM 2011, need to manually assign relationship between two entities using SDK.

This example explains how to associate and disassociate N:N(Many to Many) relationship records in CRM 2011 thru SDK. In my example I have N:N relationship between Contact and Account. Relationship name is ls_contact_account.


       // Creates the custom many-to-many relationship between the contact and account.
        public void CreateContactAccountRelationship(IOrganizationService service, EntityReference accountRef, EntityReference contactRef)
        {
            //If one of the ID's is null, do nothing
            if (accountRef == null) return;
            if (contactRef == null) return;
            if (accountRef.LogicalName != "account") return;
            if (contactRef.LogicalName != "contact") return;

            var accountID = accountRef.Id;
            var contactId = contactRef.Id;

            //The relationship schema to create
            string relationshipName = "ls_contact_account";

            //Create a query that will check to see if the relationship already exists between this account and contact
            QueryExpression query = new QueryExpression(relationshipName)
            {
                NoLock = true,
                ColumnSet = new ColumnSet(false),//only get the row ID, since we don't need any actual values
                Criteria =
                {
                    Filters =
			        {
				        new FilterExpression
				        {
					        FilterOperator = LogicalOperator.And,
					        Conditions =
					        {
                                //Get the row for the relationship where the account and contact are the account and contact passed in
						        new ConditionExpression("accountid", ConditionOperator.Equal, accountID.ToString()),
						        new ConditionExpression("contactid", ConditionOperator.Equal, contactId.ToString()),
					        },
				        },
			        }
                }
            };
            var result = service.RetrieveMultiple(query);
            //Check if the relationship was not found
            if (result == null || result.Entities == null || result.Entities.Count < 1)
            {
                //The relationship was not found, so create it
                service.Associate(accountRef.LogicalName, accountRef.Id, new Relationship(relationshipName), new EntityReferenceCollection() { contactRef });
            }
        }

       // Deletes the many-to-many relationship record between the contact and account.
        public void DeleteContactAccountRelationship(IOrganizationService service, EntityReference accountRef, EntityReference contactRef)
        {
            //If one of the ID's is null, do nothing
            if (accountRef == null) return;
            if (contactRef == null) return;
            if (accountRef.LogicalName != "account") return;
            if (contactRef.LogicalName != "contact") return;

            var accountID = accountRef.Id;
            var contactId = contactRef.Id;

            //The relationship schema to create
            string relationshipName = "ls_contact_account";

            //Create a query that will check to see if the relationship already exists between this account and contact
            QueryExpression query = new QueryExpression(relationshipName)
            {
                NoLock = true,
                ColumnSet = new ColumnSet(false),//only get the row ID, since we don't need any actual values
                Criteria =
                {
                    Filters =
			        {
				        new FilterExpression
				        {
					        FilterOperator = LogicalOperator.And,
					        Conditions =
					        {
                                //Get the row for the relationship where the account and contact are the account
						        new ConditionExpression("accountid", ConditionOperator.Equal, accountID.ToString()),
						        new ConditionExpression("contactid", ConditionOperator.Equal, contactId.ToString()),
					        },
				        },
			        }
                }
            };
            var result = service.RetrieveMultiple(query);
            //check if record exists
            if (result != null && result.Entities != null && result.Entities.Count > 0)
            {
                //Delete the N:N relation
                service.Disassociate(accountRef.LogicalName, accountRef.Id, new Relationship(relationshipName), new EntityReferenceCollection() { contactRef });
            }
        }