2

I am having problems getting a custom workflow activity working. I have stripped it back to the most simple code:

// TODO: Implement your custom Workflow business logic.

// Get the context
var xrmContext = new OrganizationServiceContext(service);

// Get an object that we can update
var client = (from a in xrmContext.CreateQuery("account")
    where a.GetAttributeValue<Guid>("accountid") == new Guid("bfa273d1-d34c-e511-80cc-00155d021c08")
    select a).Single();

// Make a change
client.Attributes["name"] = "Gray Test A - CHANGED";

// Write it out
xrmContext.UpdateObject(client);
xrmContext.SaveChanges();

If you have create a workflow you will see that it doesn't get much simpler than this:

  • Get the context
  • Get an account record
  • Make the simplest of changes
  • Update and Save.

I get the following error in the trace log:

[2016-02-26 15:15:09.328] Process:CrmAsyncService |Organization:00000000-0000-0000-0000-000000000000 |Thread:   36 |Category: Platform |User: 00000000-0000-0000-0000-000000000000 |Level: Error |ReqId: 00000000-0000-0000-0000-000000000000 | ExceptionConverter.ConvertMessageAndErrorCode  ilOffset = 0x23B
>   System.InvalidOperationException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #5CC91FB6: System.InvalidOperationException: The entity is read-only and the 'Id' property cannot be modified. Use the context to update the entity instead.
>   at Microsoft.Xrm.Sdk.Entity.set_Id(Guid value)
>   at Microsoft.Crm.Extensibility.ProxyPluginExecutionContext.CopyModifiedEntityAttributes(PipelineConversionContext context, Entity originalEntity, Entity newEntity)
>   at Microsoft.Crm.Extensibility.ProxyPluginExecutionContext.ConvertPropertyBagToParameterCollection(PipelineExecutionContext context, PropertyBag propertyBag, ParameterCollection originalParameterCollection)
>   at Microsoft.Crm.Extensibility.ProxyPluginExecutionContext.Dispose(Boolean disposing)
>   at Microsoft.Crm.Extensibility.VersionedPluginProxyStepBase.GetImages(PipelineExecutionContext context, Object pluginDefinition)
>   at Microsoft.Crm.Extensibility.ImageRetrievalStep.MergeEntityRequests(PipelineExecutionContext context, Dictionary`2 entityRequests)
>   at Microsoft.Crm.Extensibility.ImageRetrievalStep.Execute(PipelineExecutionContext context)
>   at Microsoft.Crm.Extensibility.PipelineInstrumentationHelper.Execute(Boolean instrumentationEnabled, String stopwatchName, ExecuteWithInstrumentation action)
>   at Microsoft.Crm.Extensibility.Pipeline.Execute(PipelineExecutionContext context)
>   at Microsoft.Crm.Extensibility.MessageProcessor.<>c__DisplayClass1.<RunStage>b__0()
>   at Microsoft.Crm.Extensibility.PipelineInstrumentationHelper.Execute(Boolean instrumentationEnabled, String stopwatchName, ExecuteWithInstrumentation action)
>   at Microsoft.Crm.Extensibility.MessageProcessor.RunStage(PipelineExecutionContext context, Int32 pipelineStage)
>   at Microsoft.Crm.Extensibility.MessageProcessor.Execute(PipelineExecutionContext context)
>   at Microsoft.Crm.Extensibility.InternalMessageDispatcher.Execute(PipelineExecutionContext context)
>   at Microsoft.Crm.Extensibility.ExternalMessageDispatcher.ExecuteInternal(IInProcessOrganizationServiceFactory serviceFactory, IPlatformMessageDispatcherFactory dispatcherFactory, String messageName, String requestName, Int32 primaryObjectTypeCode, Int32 secondaryObjectTypeCode, ParameterCollection fields, CorrelationToken correlationToken, CallerOriginToken originToken, UserAuth userAuth, Guid callerId, Guid transactionContextId, Int32 invocationSource, Nullable`1 requestId, Version endpointVersion)
>   at Microsoft.Crm.Extensibility.OrganizationSdkServiceInternal.ExecuteRequestRequestWithInstrumentation(OrganizationRequest request, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType, UserAuth userAuth, Guid targetUserId, OrganizationContext context, Boolean returnResponse, Boolean checkAdminMode, Object operation)
>   at Microsoft.Crm.Extensibility.OrganizationSdkServiceInternal.ExecuteRequest(OrganizationRequest request, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType, UserAuth userAuth, Guid targetUserId, OrganizationContext context, Boolean returnResponse, Boolean checkAdminMode)
>   at Microsoft.Crm.Extensibility.OrganizationSdkServiceInternal.ExecuteRequest(OrganizationRequest request, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType, Boolean checkAdminMode)
>   at Microsoft.Crm.Extensibility.OrganizationSdkServiceInternal.Execute(OrganizationRequest request, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType, Boolean checkAdminMode)

I cannot understand why I cannot do this most simple of operations.

Can anyone shed any light? Thanks, Gray

James Wood
  • 17,286
  • 4
  • 46
  • 89
GrayDS
  • 363
  • 1
  • 6
  • 18
  • I think you have a line like client.Id = someguid; or client["primarykey"]=someguid, this can cause that error – Guido Preite Feb 26 '16 at 16:02
  • Guido: The code I posted is the entirety of the code (other than the boilerplate workflow activity code). I am literally getting an entity, changing one value, and trying to save it back. I am not setting the .Id property of the accountid attribute value anywhere. – GrayDS Feb 26 '16 at 16:17
  • 2
    Although it doesn't answer why this code is problematic, I find it cleaner to set up a new entity object, copy the id from the returned result of the query, set the attribute in the new entity object, and call service.update on that object. This way the audit history isn't clogged up with a bunch of "updated fields" that have the same value before and after the update action. It also leverages the CRM API's method of updating data – Joseph Duty Feb 26 '16 at 18:09
  • I just tried to recreate in an CRM Online 2016 org and could not recreate the situation. This was an issue in CRM 2011 but was fixed in Rollup 7 so I don't know how it would come back in CRM 2015. – Nicknow Feb 27 '16 at 00:59
  • @Joseph-duty: As it happens I usually do it this way. I was actually trying to avoid the possibility of people replying with 'see where you set the Id ... that's read only', so showed the long way round. – GrayDS Feb 29 '16 at 07:58
  • @nicknow: Many thanks for taking the time. This is really confirming my growing opinion that this is environmental. Maybe something off with the configuration of the Async service? – GrayDS Feb 29 '16 at 07:59
  • so when you try the way I suggested, you still get the same result? – Joseph Duty Mar 01 '16 at 13:36

1 Answers1

1

Try to attach the record to the context before Save, like this:

xrmContext.ClearChanges();
if (!xrmContext.IsAttached(client)) xrmContext.Attach(client);
xrmContext.UpdateObject(client);
xrmContext.SaveChanges();
Ahmed THADI
  • 231
  • 1
  • 5