Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserialisation in the ToWorkflowInstance() duplicates List items due to not set ObjectCreationHandling = ObjectCreationHandling.Replace in the JsonSerializerSettings #1270

Open
michalkrzych opened this issue Jun 5, 2024 · 0 comments

Comments

@michalkrzych
Copy link

Hello. I was trying out the Workflow Core library recently and found a bug in the deserialisation in the ToWorkflowInstance() method when using SqlServer as the persistence (which uses the EntityFrameworkPersistenceProvider under the hood).

Basically,

result.Data = JsonConvert.DeserializeObject(instance.Data, SerializerSettings);

is duplicating List items due a JsonSerializerSetting, ObjectCreationHandling = ObjectCreationHandling.Replace not set. This in turn, causes all workflow steps to duplicate the items in lists.

More about the ObjectCreationHandling setting here and it's the same problem as described here.

To reproduce:

  1. you need to configure your own SQL persistance
  2. then go into ToWorkflowInstance() and before deserialising assign instance.Data some sample json which contains a list with items, you can use mine, ex.
instance.Data = "{\"$type\":\"AtlasWorkflowEngine.Services.Workflows.TestWorkflow.TestData, AtlasWorkflowEngine.Services\",\"ApprovalStages\":{\"$type\":\"System.Collections.Generic.List`1[[AtlasWorkflowEngine.Services.Workflows.TestWorkflow.TestStage, AtlasWorkflowEngine.Services]], System.Private.CoreLib\",\"$values\":[{\"$type\":\"AtlasWorkflowEngine.Services.Workflows.TestWorkflow.TestStage, AtlasWorkflowEngine.Services\",\"StageOrder\":1,\"StageName\":\"Stage 1.1\",\"ApprovedBy\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[\"[email protected]\"]},\"RejectedBy\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[]},\"ResponseTimes\":{\"$type\":\"System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.DateTime, System.Private.CoreLib]], System.Private.CoreLib\"},\"RequiredApprovers\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[\"[email protected]\",\"[email protected]\"]},\"ApprovalEventId\":\"4c3d8dbb-f0f1-4b9f-b4a8-39d70f213c69\",\"RequireAllApprovers\":true,\"StageIsApproved\":false,\"StageIsRejected\":false},{\"$type\":\"AtlasWorkflowEngine.Services.Workflows.TestWorkflow.TestStage, AtlasWorkflowEngine.Services\",\"StageOrder\":1,\"StageName\":\"Stage 1.2\",\"ApprovedBy\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[]},\"RejectedBy\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[]},\"ResponseTimes\":{\"$type\":\"System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.DateTime, System.Private.CoreLib]], System.Private.CoreLib\"},\"RequiredApprovers\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[\"[email protected]\",\"[email protected]\",\"[email protected]\"]},\"ApprovalEventId\":\"acb565b7-26cc-47d8-ad54-c0dbcbbe64e8\",\"RequireAllApprovers\":false,\"StageIsApproved\":false,\"StageIsRejected\":false},{\"$type\":\"AtlasWorkflowEngine.Services.Workflows.TestWorkflow.TestStage, AtlasWorkflowEngine.Services\",\"StageOrder\":2,\"StageName\":\"Stage 2\",\"ApprovedBy\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[]},\"RejectedBy\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[]},\"ResponseTimes\":{\"$type\":\"System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.DateTime, System.Private.CoreLib]], System.Private.CoreLib\"},\"RequiredApprovers\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[\"[email protected]\"]},\"ApprovalEventId\":\"4e28761f-2544-4f64-9f88-38278c2828ed\",\"RequireAllApprovers\":true,\"StageIsApproved\":false,\"StageIsRejected\":false}]},\"CurrentStage\":{\"$type\":\"AtlasWorkflowEngine.Services.Workflows.TestWorkflow.TestStage, AtlasWorkflowEngine.Services\",\"StageOrder\":1,\"StageName\":\"Stage 1.1\",\"ApprovedBy\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[\"[email protected]\"]},\"RejectedBy\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[]},\"ResponseTimes\":{\"$type\":\"System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.DateTime, System.Private.CoreLib]], System.Private.CoreLib\"},\"RequiredApprovers\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[\"[email protected]\",\"[email protected]\"]},\"ApprovalEventId\":\"4c3d8dbb-f0f1-4b9f-b4a8-39d70f213c69\",\"RequireAllApprovers\":true,\"StageIsApproved\":false,\"StageIsRejected\":false},\"CurrentStages\":{\"$type\":\"System.Collections.Generic.List`1[[AtlasWorkflowEngine.Services.Workflows.TestWorkflow.TestStage, AtlasWorkflowEngine.Services]], System.Private.CoreLib\",\"$values\":[{\"$type\":\"AtlasWorkflowEngine.Services.Workflows.TestWorkflow.TestStage, AtlasWorkflowEngine.Services\",\"StageOrder\":1,\"StageName\":\"Stage 1.1\",\"ApprovedBy\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[\"[email protected]\"]},\"RejectedBy\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[]},\"ResponseTimes\":{\"$type\":\"System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.DateTime, System.Private.CoreLib]], System.Private.CoreLib\"},\"RequiredApprovers\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[\"[email protected]\",\"[email protected]\"]},\"ApprovalEventId\":\"4c3d8dbb-f0f1-4b9f-b4a8-39d70f213c69\",\"RequireAllApprovers\":true,\"StageIsApproved\":false,\"StageIsRejected\":false},{\"$type\":\"AtlasWorkflowEngine.Services.Workflows.TestWorkflow.TestStage, AtlasWorkflowEngine.Services\",\"StageOrder\":1,\"StageName\":\"Stage 1.2\",\"ApprovedBy\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[]},\"RejectedBy\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[]},\"ResponseTimes\":{\"$type\":\"System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.DateTime, System.Private.CoreLib]], System.Private.CoreLib\"},\"RequiredApprovers\":{\"$type\":\"System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib\",\"$values\":[\"[email protected]\",\"[email protected]\",\"[email protected]\"]},\"ApprovalEventId\":\"acb565b7-26cc-47d8-ad54-c0dbcbbe64e8\",\"RequireAllApprovers\":false,\"StageIsApproved\":false,\"StageIsRejected\":false}]}}";
  1. Step over and you will see the duplicated items in lists. If you use the json I provided above, the expected count for the ApprovedBy is 1 and RequiredApprovers 2, however the counts are getting doubled each time the ToWorkflowInstance() is being called.

image

I believe the fix is to simply set the ObjectCreationHandling = ObjectCreationHandling.Replace like this:

private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings { 
    TypeNameHandling = TypeNameHandling.All,
    ObjectCreationHandling = ObjectCreationHandling.Replace
};

but as I have a very limited knowledge and understanding of this library I kindly ask for your assistance in evaluating the impacts and/or possible side effects this might have on the rest of the library.

I'm happy to create a pull request for this "bugfix" and cross reference with this thread this afternoon.

michalkrzych pushed a commit to michalkrzych/workflow-core that referenced this issue Jun 5, 2024
danielgerlag added a commit that referenced this issue Aug 2, 2024
…n-duplication

#1270 Fixed list items deserialization duplication
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant