Skip to content

[cases] Add extensions for workflow case data conversions, similar to case.DataAs#885

Draft
dkarkanas wants to merge 3 commits intodevelopfrom
feature/case-management/wf-extensions
Draft

[cases] Add extensions for workflow case data conversions, similar to case.DataAs#885
dkarkanas wants to merge 3 commits intodevelopfrom
feature/case-management/wf-extensions

Conversation

@dkarkanas
Copy link
Copy Markdown
Contributor

@dkarkanas dkarkanas commented Jan 21, 2026

A propsed way to avoid duplicate extension code in solutions and workflow activities, when the developer wants to access typed case data from wf activities.

The naming is using prefix to avoid confusion with the "original" convertors:

and

Copilot AI review requested due to automatic review settings January 21, 2026 15:31
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds workflow-focused extension methods to convert Integrations.Case.Data into strongly-typed objects or JsonNode, mirroring the behavior of case.DataAs in the core cases models.

Changes:

  • Introduces CaseWorkflowDataAs<TData> / CaseWorkflowDataAsJsonNode extensions for Indice.Features.Cases.Workflows.Integrations.Case.
  • Minor cleanup: reorder using directives in ActivityExecutionContextExtensions.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs New extensions to deserialize Integrations.Case.Data to typed objects / JsonNode.
src/Indice.Features.Cases.Workflows/Extensions/ActivityExecutionContextExtensions.cs Reorders using directives (no functional change).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs Outdated
Comment thread src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs Outdated
if (@case.Data is JsonElement jsonElement) {
if (typeof(TData) == typeof(string)) {
// When the requested type is string, return the raw JSON text.
return (TData)(object)jsonElement.GetRawText();

Check warning

Code scanning / CodeQL

Useless upcast Warning

There is no need to upcast from
String
to
Object
- the conversion can be done implicitly.

Copilot Autofix

AI 3 months ago

In general, to fix a “useless upcast” you remove the explicit cast where the compiler already performs an implicit conversion (typically from a derived/reference type to object or a base type) and where that cast does not affect overload resolution or generics. The goal is to preserve behavior while simplifying the code.

Here, the specific pattern is return (TData)(object)jsonElement.GetRawText(); inside CaseWorkflowDataAs<TData>. The inner (object) cast is redundant because jsonElement.GetRawText() is already a string, which implicitly converts to object. The outer cast to TData is still required to satisfy the generic return type, but the intermediate upcast is unnecessary. The best fix is to remove only the (object) cast, changing line 30 to return (TData)(jsonElement.GetRawText() as object); is not necessary; we can simply rely on the fact that C# allows an explicit cast from string to TData via the existing syntax: return (TData)(object)jsonElement.GetRawText(); can be simplified to return (TData)(object)jsonElement.GetRawText();return (TData)(object)jsonElement.GetRawText();? Actually the minimal and correct change is to remove the inner cast entirely: return (TData)(object)jsonElement.GetRawText();return (TData)jsonElement.GetRawText();. This keeps the logic intact: when TData is string, the cast to TData is valid and returns the raw JSON text; for any other TData, this line is only executed when typeof(TData) == typeof(string), so behavior is unchanged.

This requires editing only src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs, in the body of CaseWorkflowDataAs<TData>, replacing the specific return statement inside the if (typeof(TData) == typeof(string)) block that handles JsonElement. No new methods or imports are needed.

Suggested changeset 1
src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs b/src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs
--- a/src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs
+++ b/src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs
@@ -27,7 +27,7 @@
         if (@case.Data is JsonElement jsonElement) {
             if (typeof(TData) == typeof(string)) {
                 // When the requested type is string, return the raw JSON text.
-                return (TData)(object)jsonElement.GetRawText();
+                return (TData)jsonElement.GetRawText();
             }
 
             return jsonElement.Deserialize<TData>(options);
EOF
@@ -27,7 +27,7 @@
if (@case.Data is JsonElement jsonElement) {
if (typeof(TData) == typeof(string)) {
// When the requested type is string, return the raw JSON text.
return (TData)(object)jsonElement.GetRawText();
return (TData)jsonElement.GetRawText();
}

return jsonElement.Deserialize<TData>(options);
Copilot is powered by AI and may make mistakes. Always verify output.

var json = JsonSerializer.Serialize(@case.Data, options);
if (typeof(TData) == typeof(string)) {
return (TData)(object)json;

Check warning

Code scanning / CodeQL

Useless upcast Warning

There is no need to upcast from
String
to
Object
- the conversion can be done implicitly.

Copilot Autofix

AI 3 months ago

In general, a "useless upcast" warning is resolved by removing an explicit cast where the compiler will automatically perform the conversion (e.g., from a more derived type to a base type like object). Here, on line 38, json is a string, and C# implicitly converts string to object, so (object)json is redundant.

The best minimal fix that preserves existing behavior is to remove only the (object) upcast and keep the generic cast to TData. Specifically, change:

return (TData)(object)json;

to:

return (TData)json;

This keeps the method’s semantics the same: when TData is string, the cast is effectively a no-op; when TData is something else but typeof(TData) == typeof(string) (which cannot happen), the logic would be unreachable anyway. No changes to imports or other methods are required. The edit is confined to src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs, in the CaseWorkflowDataAs<TData> method, near the bottom of that method where the non-JsonElement path handles the string case.

Suggested changeset 1
src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs b/src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs
--- a/src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs
+++ b/src/Indice.Features.Cases.Workflows/Extensions/CasesExtensions.cs
@@ -35,7 +35,7 @@
 
         var json = JsonSerializer.Serialize(@case.Data, options);
         if (typeof(TData) == typeof(string)) {
-            return (TData)(object)json;
+            return (TData)json;
         }
         return JsonSerializer.Deserialize<TData>(json, options);
     }
EOF
@@ -35,7 +35,7 @@

var json = JsonSerializer.Serialize(@case.Data, options);
if (typeof(TData) == typeof(string)) {
return (TData)(object)json;
return (TData)json;
}
return JsonSerializer.Deserialize<TData>(json, options);
}
Copilot is powered by AI and may make mistakes. Always verify output.
@dkarkanas
Copy link
Copy Markdown
Contributor Author

dkarkanas commented Jan 23, 2026

We discussed with @cleftheris the proposed way for this, which is to use JsonNode instead of dynamic (CaseData), and object (IntegrationCaseData).

@dkarkanas dkarkanas marked this pull request as draft January 27, 2026 14:55
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

Successfully merging this pull request may close these issues.

4 participants