dynamics-crmdynamics-crm-2013dynamics-crm-365

Using CrmSdk.CoreAssemblies v9 with Dynamics CRM 2013 - ConcurrencyBehavior serializing


I maintain an API that needs to read/write data to CRM2013, so far I have been working with CrmSdk version 6.1.2. However recently there has been a need to adapt the API to also work with an organization using CRM365 which requires features from the later versions of the CrmSdk, so I've had to update the package.

Now when I try to save changes to CRM2013 through OrganizationServiceContext I am getting the error "The formatter threw an exception while trying to deserialize the message: 'Error in line 1 position 3352. Element 'http://schemas.datacontract.org/2004/07/System.Collections.Generic:value' contains data from a type that maps to the name 'http://schemas.microsoft.com/xrm/7.1/Contracts:ConcurrencyBehavior'. The deserializer has no knowledge of any type that maps to this name. Consider changing the implementation of the ResolveName method on your DataContractResolver to return a non-null value for name 'ConcurrencyBehavior' and namespace 'http://schemas.microsoft.com/xrm/7.1/Contracts'.'."

This error starts occurring right after updating the CrmSdk version with no other changes to my code. Is there any workaround for this? Or is there some version of CrmSdk that works with both CRM365 and CRM2013?


Solution

  • Create a custom class implementing the IOrganizationService interface. This class gets an original IOrganizationService instance injected in its constructor, e.g. a ServiceClient object.

    The new OrganizationService class implements the interface and simply redirects calls for all requests. Only the Update and Delete messages need special treatment: for these the ConcurrencyBehavior parameter must be stripped from the request.

    class OrganizationService : IOrganizationService
    {
        private readonly IOrganizationService organizationService;
    
        public OrganizationService(IOrganizationService organizationService)
        {
            this.organizationService = organizationService;
        }
    
        public OrganizationResponse Execute(OrganizationRequest request)
        {
            if (request is UpdateRequest || request is DeleteRequest)
            {
                return organizationService.Execute(new OrganizationRequest(request.RequestName)
                {
                    ["Target"] = request["Target"]
                });
            }
    
            return organizationService.Execute(request);
        }
    
        (...)
    }
    

    Create an OrganizationServiceContext like this:

    var context = new OrganizationServiceContext(new OrganizationService(serviceClient));
    

    See also Optimistic concurrency - MS Learn.