From ff991b8ee1e2479c1447dd12bd5535e10eab04f9 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 25 Feb 2026 14:40:37 +0100 Subject: [PATCH 1/4] Extract and copy metadata when activity type is not found in `ActivityJsonConverter`. --- .../Serialization/Converters/ActivityJsonConverter.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs index 125bfe847b..abd1af6804 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs @@ -54,6 +54,17 @@ public override IActivity Read(ref Utf8JsonReader reader, Type typeToConvert, Js notFoundActivity.OriginalActivityJson = activityRoot.ToString(); notFoundActivity.SetDisplayText($"Not Found: {activityTypeName}"); notFoundActivity.SetDescription($"Could not find activity type {activityTypeName} with version {activityTypeVersion}"); + + // Extract and copy metadata from the not found activity JSON + if (doc.RootElement.TryGetProperty("metadata", out var metadataElement)) + { + var metadata = JsonSerializer.Deserialize>(metadataElement.GetRawText(), clonedOptions); + if (metadata != null) + { + notFoundActivity.Metadata = metadata; + } + } + return notFoundActivity; } From 4f37a8127cb336a3de3923df6fa2fb01fe6bdb47 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 25 Feb 2026 18:58:14 +0100 Subject: [PATCH 2/4] Improve `ActivityJsonConverter`: Correct metadata extraction to read from NotFoundActivity wrapper. --- .../Converters/ActivityJsonConverter.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs index abd1af6804..5b893dc5e2 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs @@ -55,13 +55,15 @@ public override IActivity Read(ref Utf8JsonReader reader, Type typeToConvert, Js notFoundActivity.SetDisplayText($"Not Found: {activityTypeName}"); notFoundActivity.SetDescription($"Could not find activity type {activityTypeName} with version {activityTypeVersion}"); - // Extract and copy metadata from the not found activity JSON - if (doc.RootElement.TryGetProperty("metadata", out var metadataElement)) + // Extract and copy metadata from the outer NotFoundActivity JSON wrapper (doc.RootElement). + // Note: activityRoot may contain the inner originalActivityJson, so we must read from doc.RootElement + // to get the metadata that was added to the NotFoundActivity wrapper itself. + if (doc.RootElement.TryGetProperty("metadata", out var outerMetadataElement)) { - var metadata = JsonSerializer.Deserialize>(metadataElement.GetRawText(), clonedOptions); - if (metadata != null) + var outerMetadata = JsonSerializer.Deserialize>(outerMetadataElement.GetRawText(), clonedOptions); + if (outerMetadata != null) { - notFoundActivity.Metadata = metadata; + notFoundActivity.Metadata = outerMetadata; } } From daa0f571ec2fffdb054386b6395c76c6059b805f Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 25 Feb 2026 19:04:14 +0100 Subject: [PATCH 3/4] Reposition activity description and display text assignment to follow metadata extraction in `ActivityJsonConverter`. --- .../Serialization/Converters/ActivityJsonConverter.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs index 5b893dc5e2..1203aa8cbf 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs @@ -52,8 +52,6 @@ public override IActivity Read(ref Utf8JsonReader reader, Type typeToConvert, Js notFoundActivity.MissingTypeName = activityTypeName; notFoundActivity.MissingTypeVersion = activityTypeVersion; notFoundActivity.OriginalActivityJson = activityRoot.ToString(); - notFoundActivity.SetDisplayText($"Not Found: {activityTypeName}"); - notFoundActivity.SetDescription($"Could not find activity type {activityTypeName} with version {activityTypeVersion}"); // Extract and copy metadata from the outer NotFoundActivity JSON wrapper (doc.RootElement). // Note: activityRoot may contain the inner originalActivityJson, so we must read from doc.RootElement @@ -67,6 +65,10 @@ public override IActivity Read(ref Utf8JsonReader reader, Type typeToConvert, Js } } + // Set display text and description after metadata assignment to ensure they always reflect the current state + notFoundActivity.SetDisplayText($"Not Found: {activityTypeName}"); + notFoundActivity.SetDescription($"Could not find activity type {activityTypeName} with version {activityTypeVersion}"); + return notFoundActivity; } From 2b4cd4f66f244e44956b50e233aa1b1e117b6c72 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 25 Feb 2026 20:02:05 +0100 Subject: [PATCH 4/4] Update src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Serialization/Converters/ActivityJsonConverter.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs index 1203aa8cbf..29da39c2f7 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs @@ -53,9 +53,10 @@ public override IActivity Read(ref Utf8JsonReader reader, Type typeToConvert, Js notFoundActivity.MissingTypeVersion = activityTypeVersion; notFoundActivity.OriginalActivityJson = activityRoot.ToString(); - // Extract and copy metadata from the outer NotFoundActivity JSON wrapper (doc.RootElement). - // Note: activityRoot may contain the inner originalActivityJson, so we must read from doc.RootElement - // to get the metadata that was added to the NotFoundActivity wrapper itself. + // Extract metadata from doc.RootElement rather than activityRoot. + // In round-trip scenarios, activityRoot may have been reassigned to the inner originalActivityJson (see line 37), + // but we want the metadata from the current activity being deserialized, which represents the NotFoundActivity + // placeholder's position and annotations in the designer. if (doc.RootElement.TryGetProperty("metadata", out var outerMetadataElement)) { var outerMetadata = JsonSerializer.Deserialize>(outerMetadataElement.GetRawText(), clonedOptions);