diff --git a/src/modules/Elsa.Persistence.EntityFrameworkCore/Modules/Management/WorkflowInstanceStore.cs b/src/modules/Elsa.Persistence.EntityFrameworkCore/Modules/Management/WorkflowInstanceStore.cs
index f488673f0..36ca1b8ea 100644
--- a/src/modules/Elsa.Persistence.EntityFrameworkCore/Modules/Management/WorkflowInstanceStore.cs
+++ b/src/modules/Elsa.Persistence.EntityFrameworkCore/Modules/Management/WorkflowInstanceStore.cs
@@ -4,6 +4,7 @@ using Elsa.Common.Entities;
using Elsa.Common.Models;
using Elsa.Persistence.EntityFrameworkCore.Common;
using Elsa.Persistence.EntityFrameworkCore.Extensions;
+using Elsa.Workflows.Core.Models;
using Elsa.Workflows.Core.Serialization;
using Elsa.Workflows.Core.State;
using Elsa.Workflows.Management.Entities;
@@ -130,13 +131,13 @@ public class EFCoreWorkflowInstanceStore : IWorkflowInstanceStore
{
}
- public WorkflowInstanceState(WorkflowState workflowState, WorkflowFault? fault)
+ public WorkflowInstanceState(WorkflowState workflowState, WorkflowFaultState? fault)
{
WorkflowState = workflowState;
Fault = fault;
}
public WorkflowState WorkflowState { get; init; } = default!;
- public WorkflowFault? Fault { get; set; }
+ public WorkflowFaultState? Fault { get; set; }
}
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Get/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Get/Models.cs
index a557411aa..756906550 100644
--- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Get/Models.cs
+++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Get/Models.cs
@@ -19,7 +19,7 @@ public class Response
public WorkflowSubStatus SubStatus { get; set; }
public string? CorrelationId { get; set; }
public string? Name { get; set; }
- public WorkflowFault? Fault { get; set; }
+ public WorkflowFaultState? Fault { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public DateTimeOffset? LastExecutedAt { get; set; }
public DateTimeOffset? FinishedAt { get; set; }
diff --git a/src/modules/Elsa.Workflows.Core/Activities/Fault.cs b/src/modules/Elsa.Workflows.Core/Activities/Fault.cs
new file mode 100644
index 000000000..f695a4ec8
--- /dev/null
+++ b/src/modules/Elsa.Workflows.Core/Activities/Fault.cs
@@ -0,0 +1,32 @@
+using System.Runtime.CompilerServices;
+using System.Text.Json.Serialization;
+using Elsa.Workflows.Core.Attributes;
+using Elsa.Workflows.Core.Models;
+
+namespace Elsa.Workflows.Core.Activities;
+
+///
+/// Faults the workflow.
+///
+[Activity("Elsa", "Primitives", "Faults the workflow.")]
+public class Fault : ActivityBase
+{
+ ///
+ [JsonConstructor]
+ public Fault([CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : base(source, line)
+ {
+ }
+
+ ///
+ /// The message to include with the fault.
+ ///
+ [Input(Description = "The message to include with the fault.")]
+ public Input Message { get; set; } = default!;
+
+ ///
+ protected override void Execute(ActivityExecutionContext context)
+ {
+ var message = Message.Get(context);
+ throw new Exception(message);
+ }
+}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Core/Implementations/WorkflowStateSerializer.cs b/src/modules/Elsa.Workflows.Core/Implementations/WorkflowStateSerializer.cs
index 55aa98896..5792b7ff1 100644
--- a/src/modules/Elsa.Workflows.Core/Implementations/WorkflowStateSerializer.cs
+++ b/src/modules/Elsa.Workflows.Core/Implementations/WorkflowStateSerializer.cs
@@ -20,7 +20,8 @@ public class WorkflowStateSerializer : IWorkflowStateSerializer
CorrelationId = workflowExecutionContext.CorrelationId,
Status = workflowExecutionContext.Status,
SubStatus = workflowExecutionContext.SubStatus,
- Bookmarks = workflowExecutionContext.Bookmarks
+ Bookmarks = workflowExecutionContext.Bookmarks,
+ Fault = SerializeFault(workflowExecutionContext.Fault)
};
SerializeProperties(state, workflowExecutionContext);
@@ -52,39 +53,7 @@ public class WorkflowStateSerializer : IWorkflowStateSerializer
workflowExecutionContext.Properties = state.Properties.Properties;
}
- private void GetOutput(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
- {
- foreach (var node in workflowExecutionContext.Nodes)
- GetOutput(state, node);
- }
-
- private void GetOutput(WorkflowState state, ActivityNode activityNode)
- {
- var output = GetOutputFrom(activityNode);
-
- if (output.Any())
- state.ActivityOutput.Add(activityNode.NodeId, output);
- }
-
- private void SetOutput(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
- {
- foreach (var entry in state.ActivityOutput)
- {
- var activityId = entry.Key;
- var node = workflowExecutionContext.FindNodeById(activityId);
- var activityType = node.Activity.GetType();
-
- foreach (var outputEntry in entry.Value)
- {
- var propertyName = outputEntry.Key;
- var propertyValue = outputEntry.Value;
- var propertyInfo = activityType.GetProperty(propertyName, BindingFlags.Public)!;
- propertyInfo.SetValue(node, propertyValue);
- }
- }
- }
-
- private void DeserializeCompletionCallbacks(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
+ private static void DeserializeCompletionCallbacks(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
{
foreach (var completionCallbackEntry in state.CompletionCallbacks)
{
@@ -96,7 +65,7 @@ public class WorkflowStateSerializer : IWorkflowStateSerializer
}
}
- private void SerializeCompletionCallbacks(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
+ private static void SerializeCompletionCallbacks(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
{
// Assert all referenced owner contexts exist.
foreach (var completionCallback in workflowExecutionContext.CompletionCallbacks)
@@ -111,7 +80,7 @@ public class WorkflowStateSerializer : IWorkflowStateSerializer
state.CompletionCallbacks = completionCallbacks.ToList();
}
- private void SerializeActivityExecutionContexts(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
+ private static void SerializeActivityExecutionContexts(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
{
ActivityExecutionContextState CreateActivityExecutionContextState(ActivityExecutionContext activityExecutionContext)
{
@@ -139,7 +108,7 @@ public class WorkflowStateSerializer : IWorkflowStateSerializer
state.ActivityExecutionContexts = workflowExecutionContext.ActivityExecutionContexts.Reverse().Select(CreateActivityExecutionContextState).ToList();
}
- private void DeserializeActivityExecutionContexts(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
+ private static void DeserializeActivityExecutionContexts(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
{
ActivityExecutionContext CreateActivityExecutionContext(ActivityExecutionContextState activityExecutionContextState)
{
@@ -167,7 +136,13 @@ public class WorkflowStateSerializer : IWorkflowStateSerializer
workflowExecutionContext.ActivityExecutionContexts = activityExecutionContexts;
}
+
+ private static WorkflowFaultState? SerializeFault(WorkflowFault? fault)
+ {
+ if (fault == null)
+ return null;
- private Dictionary GetOutputFrom(ActivityNode activityNode) =>
- activityNode.GetType().GetProperties(BindingFlags.Public).Where(x => x.GetCustomAttribute() != null).ToDictionary(x => x.Name, x => x.GetValue(activityNode)!);
+ var exceptionState = ExceptionState.FromException(fault.Exception);
+ return new WorkflowFaultState(exceptionState, fault.Message, fault.FaultedActivityId);
+ }
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Core/Models/WorkflowExecutionContext.cs b/src/modules/Elsa.Workflows.Core/Models/WorkflowExecutionContext.cs
index b61277ec3..d4e364031 100644
--- a/src/modules/Elsa.Workflows.Core/Models/WorkflowExecutionContext.cs
+++ b/src/modules/Elsa.Workflows.Core/Models/WorkflowExecutionContext.cs
@@ -137,6 +137,11 @@ public class WorkflowExecutionContext
///
public IDictionary