diff --git a/.github/workflows/elsa-server-and-studio.yml b/.github/workflows/elsa-server-and-studio.yml
index bd6c23243..46417543a 100644
--- a/.github/workflows/elsa-server-and-studio.yml
+++ b/.github/workflows/elsa-server-and-studio.yml
@@ -3,7 +3,7 @@ on:
workflow_dispatch:
push:
branches:
- - main
+ - patch/3.2.x
jobs:
push_to_registry:
@@ -29,7 +29,7 @@ jobs:
with:
# list of Docker images to use as base name for tags
images: |
- elsaworkflows/elsa-server-and-studio-v3
+ elsaworkflows/elsa-server-and-studio-v3-2-0-rc3
flavor: |
latest=true
# generate Docker tags based on the following events/attributes
diff --git a/.github/workflows/elsa-server.yml b/.github/workflows/elsa-server.yml
index a5bc9572a..7c50ce0c8 100644
--- a/.github/workflows/elsa-server.yml
+++ b/.github/workflows/elsa-server.yml
@@ -3,7 +3,7 @@ on:
workflow_dispatch:
push:
branches:
- - main
+ - patch/3.2.x
jobs:
push_to_registry:
@@ -29,7 +29,7 @@ jobs:
with:
# list of Docker images to use as base name for tags
images: |
- elsaworkflows/elsa-server-v3
+ elsaworkflows/elsa-server-v3-2-0-rc3
flavor: |
latest=true
# generate Docker tags based on the following events/attributes
diff --git a/.github/workflows/elsa-studio.yml b/.github/workflows/elsa-studio.yml
index ebc412655..35c8eb51a 100644
--- a/.github/workflows/elsa-studio.yml
+++ b/.github/workflows/elsa-studio.yml
@@ -3,7 +3,7 @@ on:
workflow_dispatch:
push:
branches:
- - main
+ - patch/3.2.x
jobs:
push_to_registry:
@@ -29,7 +29,7 @@ jobs:
with:
# list of Docker images to use as base name for tags
images: |
- elsaworkflows/elsa-studio-v3
+ elsaworkflows/elsa-studio-v3-2-0-rc3
flavor: |
latest=true
# generate Docker tags based on the following events/attributes
diff --git a/Directory.Build.props b/Directory.Build.props
index 19e72116b..abd6ae599 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,34 +1,35 @@
-
- Elsa Workflows Community
- 2023
+
+ Elsa Workflows Community
+ 2023
- https://github.com/elsa-workflows/elsa-core
- https://github.com/elsa-workflows/elsa-core
- git
+ https://github.com/elsa-workflows/elsa-core
+ https://github.com/elsa-workflows/elsa-core
+ git
- latest
- enable
- enable
+ latest
+ enable
+ enable
- MIT
- icon.png
+ MIT
+ icon.png
-
- https://v3.elsaworkflows.io/nuget-icon.png
-
- true
- Default
- latest
+
+ https://v3.elsaworkflows.io/nuget-icon.png
-
- true
- snupkg
- false
-
-
-
- $(NoWarn);CS0162;CS1591
-
+ true
+ Default
+ latest
+
+ true
+ snupkg
+ true
+
+
+ $(NoWarn);CS0162;CS1591
+
+
+ 3.2.0-rc3.417
+
\ No newline at end of file
diff --git a/Directory.Packages.props b/Directory.Packages.props
index ebd3dec86..f67a497e6 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -23,9 +23,9 @@
-
-
-
+
+
+
diff --git a/src/bundles/Elsa.ServerAndStudio.Web/Elsa.ServerAndStudio.Web.csproj b/src/bundles/Elsa.ServerAndStudio.Web/Elsa.ServerAndStudio.Web.csproj
index 12a7096f6..3cb1c9444 100644
--- a/src/bundles/Elsa.ServerAndStudio.Web/Elsa.ServerAndStudio.Web.csproj
+++ b/src/bundles/Elsa.ServerAndStudio.Web/Elsa.ServerAndStudio.Web.csproj
@@ -10,20 +10,20 @@
-
+
-
+
-
-
-
-
-
+
+
+
+
+
@@ -31,10 +31,10 @@
-
-
+
+
-
+
diff --git a/src/bundles/Elsa.ServerAndStudio.Web/Enums/DistributedCachingTransport.cs b/src/bundles/Elsa.ServerAndStudio.Web/Enums/DistributedCachingTransport.cs
index fc8e2f381..68971a20c 100644
--- a/src/bundles/Elsa.ServerAndStudio.Web/Enums/DistributedCachingTransport.cs
+++ b/src/bundles/Elsa.ServerAndStudio.Web/Enums/DistributedCachingTransport.cs
@@ -1,8 +1,6 @@
namespace Elsa.ServerAndStudio.Web.Enums;
-///
/// Represents the transport options for distributed caching.
-///
public enum DistributedCachingTransport
{
None,
diff --git a/src/bundles/Elsa.ServerAndStudio.Web/Enums/MassTransitBroker.cs b/src/bundles/Elsa.ServerAndStudio.Web/Enums/MassTransitBroker.cs
index 2ab461e3a..84a81d86a 100644
--- a/src/bundles/Elsa.ServerAndStudio.Web/Enums/MassTransitBroker.cs
+++ b/src/bundles/Elsa.ServerAndStudio.Web/Enums/MassTransitBroker.cs
@@ -1,8 +1,6 @@
namespace Elsa.ServerAndStudio.Web.Enums;
-///
/// Represents the type of messaging broker used in MassTransit.
-///
public enum MassTransitBroker
{
Memory,
diff --git a/src/bundles/ElsaStudioWebAssembly/ElsaStudioWebAssembly.csproj b/src/bundles/ElsaStudioWebAssembly/ElsaStudioWebAssembly.csproj
index 1cc2f891c..eba2a2fd1 100644
--- a/src/bundles/ElsaStudioWebAssembly/ElsaStudioWebAssembly.csproj
+++ b/src/bundles/ElsaStudioWebAssembly/ElsaStudioWebAssembly.csproj
@@ -13,8 +13,4 @@
-
- <_ContentIncludedByDefault Remove="wwwroot\index.html" />
-
-
diff --git a/src/clients/Elsa.Api.Client/Extensions/PropertyBagExtensions.cs b/src/clients/Elsa.Api.Client/Extensions/PropertyBagExtensions.cs
new file mode 100644
index 000000000..c27200c88
--- /dev/null
+++ b/src/clients/Elsa.Api.Client/Extensions/PropertyBagExtensions.cs
@@ -0,0 +1,41 @@
+using System.Text.Json;
+using Elsa.Api.Client.Shared.Models;
+
+namespace Elsa.Api.Client.Extensions;
+
+///
+/// Provides extension methods for the PropertyBag class.
+///
+public static class PropertyBagExtensions
+{
+ ///
+ /// Tries to retrieve a value from the PropertyBag based on the provided key.
+ /// If the specified key does not exist in the PropertyBag, the method will return the default value obtained from the defaultValue function.
+ ///
+ /// The type of the value to retrieve.
+ /// The PropertyBag to retrieve the value from.
+ /// The key of the value to retrieve.
+ /// A function that returns the default value to be returned if the key does not exist in the PropertyBag.
+ /// The value associated with the key, or the default value if the key does not exist.
+ public static T TryGetValueOrDefault(this PropertyBag propertyBag, string key, Func defaultValue)
+ {
+ if (!propertyBag.TryGetValue(key, out var value))
+ return defaultValue();
+
+ var json = (string)value;
+ return JsonSerializer.Deserialize(json);
+ }
+
+ ///
+ /// Sets a value in the PropertyBag based on the provided key.
+ /// The value is serialized using JSON.
+ ///
+ /// The PropertyBag to set the value in.
+ /// The key to associate with the value.
+ /// The value to store in the PropertyBag.
+ public static void SetValue(this PropertyBag propertyBag, string key, object value)
+ {
+ var json = JsonSerializer.Serialize(value);
+ propertyBag[key] = json;
+ }
+}
\ No newline at end of file
diff --git a/src/clients/Elsa.Api.Client/Resources/WorkflowDefinitions/Contracts/IWorkflowDefinitionsApi.cs b/src/clients/Elsa.Api.Client/Resources/WorkflowDefinitions/Contracts/IWorkflowDefinitionsApi.cs
index 102331af1..ab41f8aa1 100644
--- a/src/clients/Elsa.Api.Client/Resources/WorkflowDefinitions/Contracts/IWorkflowDefinitionsApi.cs
+++ b/src/clients/Elsa.Api.Client/Resources/WorkflowDefinitions/Contracts/IWorkflowDefinitionsApi.cs
@@ -209,6 +209,7 @@ public interface IWorkflowDefinitionsApi
/// The definition ID of the workflow definition to revert.
/// The version to revert to.
/// An optional cancellation token.
+ /// A summary view of the newly created workflow definition version.
[Post("/workflow-definitions/{definitionId}/revert/{version}")]
- Task RevertVersionAsync(string definitionId, int version, CancellationToken cancellationToken = default);
+ Task RevertVersionAsync(string definitionId, int version, CancellationToken cancellationToken = default);
}
\ No newline at end of file
diff --git a/src/clients/Elsa.Api.Client/Resources/WorkflowDefinitions/Models/WorkflowDefinition.cs b/src/clients/Elsa.Api.Client/Resources/WorkflowDefinitions/Models/WorkflowDefinition.cs
index 4a6ddb194..c93ca96a7 100644
--- a/src/clients/Elsa.Api.Client/Resources/WorkflowDefinitions/Models/WorkflowDefinition.cs
+++ b/src/clients/Elsa.Api.Client/Resources/WorkflowDefinitions/Models/WorkflowDefinition.cs
@@ -58,6 +58,11 @@ public class WorkflowDefinition : LinkedEntity
///
public IDictionary CustomProperties { get; set; } = new Dictionary();
+ ///
+ /// Stores custom information about the workflow. Can be used to store application-specific properties to associate with the workflow.
+ ///
+ public PropertyBag PropertyBag { get; set; } = new();
+
///
/// The name of the workflow provider that created this workflow, if any.
///
diff --git a/src/clients/Elsa.Api.Client/Resources/WorkflowDefinitions/Models/WorkflowDefinitionModel.cs b/src/clients/Elsa.Api.Client/Resources/WorkflowDefinitions/Models/WorkflowDefinitionModel.cs
index a617b54f3..76dba636d 100644
--- a/src/clients/Elsa.Api.Client/Resources/WorkflowDefinitions/Models/WorkflowDefinitionModel.cs
+++ b/src/clients/Elsa.Api.Client/Resources/WorkflowDefinitions/Models/WorkflowDefinitionModel.cs
@@ -55,6 +55,11 @@ public class WorkflowDefinitionModel : LinkedEntity
///
public IDictionary? CustomProperties { get; set; }
+ ///
+ /// Stores custom information about the workflow. Can be used to store application-specific properties to associate with the workflow.
+ ///
+ public PropertyBag PropertyBag { get; set; } = new();
+
///
/// Gets or sets whether the workflow definition is read-only.
///
diff --git a/src/clients/Elsa.Api.Client/Resources/WorkflowInstances/Requests/JournalFilter.cs b/src/clients/Elsa.Api.Client/Resources/WorkflowInstances/Requests/JournalFilter.cs
index 537baf49a..55f71e5e6 100644
--- a/src/clients/Elsa.Api.Client/Resources/WorkflowInstances/Requests/JournalFilter.cs
+++ b/src/clients/Elsa.Api.Client/Resources/WorkflowInstances/Requests/JournalFilter.cs
@@ -1,22 +1,17 @@
namespace Elsa.Api.Client.Resources.WorkflowInstances.Requests;
-///
/// Represents a request to list journal records.
-///
public class JournalFilter
{
- ///
/// Gets or sets the activity IDs to filter by.
- ///
public ICollection? ActivityIds { get; set; }
-
- ///
+
+ /// Gets or sets the activity node IDs to filter by.
+ public ICollection? ActivityNodeIds { get; set; }
+
/// Gets or sets the activity types to filter out.
- ///
public ICollection? ExcludedActivityTypes { get; set; }
- ///
/// Gets or sets the event types to filter by.
- ///
public ICollection? EventNames { get; set; }
}
\ No newline at end of file
diff --git a/src/clients/Elsa.Api.Client/Shared/Models/PropertyBag.cs b/src/clients/Elsa.Api.Client/Shared/Models/PropertyBag.cs
new file mode 100644
index 000000000..9abe27abc
--- /dev/null
+++ b/src/clients/Elsa.Api.Client/Shared/Models/PropertyBag.cs
@@ -0,0 +1,20 @@
+using System.Text.Json.Serialization;
+
+namespace Elsa.Api.Client.Shared.Models;
+
+/// A dictionary of values that is skipped by polymorphic serialization.
+public class PropertyBag : Dictionary
+{
+ ///
+ [JsonConstructor]
+ public PropertyBag() : base(StringComparer.OrdinalIgnoreCase)
+ {
+ }
+
+ ///
+ public PropertyBag(IDictionary dictionary) : this()
+ {
+ foreach (var kvp in dictionary)
+ Add(kvp.Key, kvp.Value);
+ }
+}
\ No newline at end of file
diff --git a/src/clients/Elsa.Api.Client/Shared/Models/WrappedInput.cs b/src/clients/Elsa.Api.Client/Shared/Models/WrappedInput.cs
index ea5c9225e..072f437fe 100644
--- a/src/clients/Elsa.Api.Client/Shared/Models/WrappedInput.cs
+++ b/src/clients/Elsa.Api.Client/Shared/Models/WrappedInput.cs
@@ -21,4 +21,5 @@ public class WrappedInput
/// Gets or sets the memory reference of this input.
///
public MemoryReference MemoryReference { get; set; } = default!;
-}
\ No newline at end of file
+}
+
diff --git a/src/modules/Elsa.Common/Extensions/PropertyBagExtensions.cs b/src/modules/Elsa.Common/Extensions/PropertyBagExtensions.cs
new file mode 100644
index 000000000..ad0359c21
--- /dev/null
+++ b/src/modules/Elsa.Common/Extensions/PropertyBagExtensions.cs
@@ -0,0 +1,67 @@
+using System.Text.Json;
+using Elsa.Common.Models;
+
+// ReSharper disable once CheckNamespace
+namespace Elsa.Extensions;
+
+///
+/// Provides extension methods for the PropertyBag class.
+///
+public static class PropertyBagExtensions
+{
+ ///
+ /// Tries to retrieve a value from the PropertyBag based on the provided key.
+ /// If the specified key does not exist in the PropertyBag, the method will return the default value obtained from the defaultValue function.
+ ///
+ /// The type of the value to retrieve.
+ /// The PropertyBag to retrieve the value from.
+ /// The key of the value to retrieve.
+ /// A function that returns the default value to be returned if the key does not exist in the PropertyBag.
+ /// Optional JSON serializer options.
+ /// The value associated with the key, or the default value if the key does not exist.
+ public static T TryGetValueOrDefault(this PropertyBag propertyBag, string key, Func defaultValue, JsonSerializerOptions? options = null)
+ {
+ if (!propertyBag.TryGetValue(key, out var value))
+ return defaultValue();
+
+ var json = (string)value;
+ return JsonSerializer.Deserialize(json, options);
+ }
+
+ ///
+ /// Tries to retrieve a value from the PropertyBag based on the provided key.
+ /// If the specified key does not exist in the PropertyBag, the method will return the default value obtained from the defaultValue function.
+ ///
+ /// The type of the value to retrieve.
+ /// The PropertyBag to retrieve the value from.
+ /// The key of the value to retrieve.
+ /// The deserialized value.
+ /// Optional JSON serializer options.
+ /// True if the value exists, false otherwise.
+ public static bool TryGetValue(this PropertyBag propertyBag, string key, out T value, JsonSerializerOptions? options = null)
+ {
+ if (!propertyBag.TryGetValue(key, out var v))
+ {
+ value = default!;
+ return false;
+ }
+
+ var json = (string)v;
+ value = JsonSerializer.Deserialize(json, options);
+ return true;
+ }
+
+ ///
+ /// Sets a value in the PropertyBag based on the provided key.
+ /// The value is serialized using JSON.
+ ///
+ /// The PropertyBag to set the value in.
+ /// The key to associate with the value.
+ /// The value to store in the PropertyBag.
+ /// /// Optional JSON serializer options.
+ public static void SetValue(this PropertyBag propertyBag, string key, object value, JsonSerializerOptions? options = null)
+ {
+ var json = JsonSerializer.Serialize(value);
+ propertyBag[key] = json;
+ }
+}
\ No newline at end of file
diff --git a/src/modules/Elsa.Common/Models/PropertyBag.cs b/src/modules/Elsa.Common/Models/PropertyBag.cs
new file mode 100644
index 000000000..0f6209e81
--- /dev/null
+++ b/src/modules/Elsa.Common/Models/PropertyBag.cs
@@ -0,0 +1,20 @@
+using System.Text.Json.Serialization;
+
+namespace Elsa.Common.Models;
+
+/// A dictionary of values that is skipped by polymorphic serialization.
+public class PropertyBag : Dictionary
+{
+ ///
+ [JsonConstructor]
+ public PropertyBag() : base(StringComparer.OrdinalIgnoreCase)
+ {
+ }
+
+ ///
+ public PropertyBag(IDictionary dictionary) : this()
+ {
+ foreach (var kvp in dictionary)
+ Add(kvp.Key, kvp.Value);
+ }
+}
\ No newline at end of file
diff --git a/src/modules/Elsa.Common/Models/VersionOptions.cs b/src/modules/Elsa.Common/Models/VersionOptions.cs
index e854587d2..25d2beb35 100644
--- a/src/modules/Elsa.Common/Models/VersionOptions.cs
+++ b/src/modules/Elsa.Common/Models/VersionOptions.cs
@@ -115,4 +115,4 @@ public struct VersionOptions
/// Returns a simple string representation of this .
///
public override string ToString() => AllVersions ? "AllVersions" : IsDraft ? "Draft" : IsLatest ? "Latest" : IsPublished ? "Published" : IsLatestOrPublished ? "LatestOrPublished" : IsLatestAndPublished ? "LatestAndPublished" : Version.ToString(CultureInfo.InvariantCulture);
-}
+}
\ No newline at end of file
diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/RunMigrationsHostedService.cs b/src/modules/Elsa.EntityFrameworkCore.Common/RunMigrationsHostedService.cs
index ebfb92beb..5d5f4e047 100644
--- a/src/modules/Elsa.EntityFrameworkCore.Common/RunMigrationsHostedService.cs
+++ b/src/modules/Elsa.EntityFrameworkCore.Common/RunMigrationsHostedService.cs
@@ -26,7 +26,6 @@ public class RunMigrationsHostedService : IHostedService where TDbCo
var dbContextFactory = scope.ServiceProvider.GetRequiredService>();
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
await dbContext.Database.MigrateAsync(cancellationToken);
- await dbContext.DisposeAsync();
}
///
diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/Configurations.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/Configurations.cs
index 5a5bc8e5f..8fdb5eaf8 100644
--- a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/Configurations.cs
+++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/Configurations.cs
@@ -17,6 +17,7 @@ internal class Configurations : IEntityTypeConfiguration, IE
builder.Ignore(x => x.Outputs);
builder.Ignore(x => x.Outcomes);
builder.Ignore(x => x.CustomProperties);
+ builder.Ignore(x => x.PropertyBag);
builder.Ignore(x => x.Options);
builder.Property("Data");
builder.Property("UsableAsActivity");
diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowDefinitionStore.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowDefinitionStore.cs
index 5b63322b2..6c966ed9d 100644
--- a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowDefinitionStore.cs
+++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowDefinitionStore.cs
@@ -177,8 +177,8 @@ public class EFCoreWorkflowDefinitionStore(EntityStore inputs,
ICollection outputs,
ICollection outcomes,
- IDictionary customProperties
+ IDictionary customProperties,
+ PropertyBag propertyBag
)
{
Options = options;
@@ -263,6 +265,7 @@ public class EFCoreWorkflowDefinitionStore(EntityStore Inputs { get; set; } = new List();
public ICollection Outputs { get; set; } = new List();
public ICollection Outcomes { get; set; } = new List();
+
+ [Obsolete("Use PropertyBag instead")]
public IDictionary CustomProperties { get; set; } = new Dictionary();
+
+ public PropertyBag PropertyBag { get; set; } = new();
}
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Expressions/Options/ExpressionOptions.cs b/src/modules/Elsa.Expressions/Options/ExpressionOptions.cs
index 460835be1..ec5ac1c19 100644
--- a/src/modules/Elsa.Expressions/Options/ExpressionOptions.cs
+++ b/src/modules/Elsa.Expressions/Options/ExpressionOptions.cs
@@ -24,16 +24,17 @@ public class ExpressionOptions
this.AddTypeAlias("Boolean");
this.AddTypeAlias("Decimal");
this.AddTypeAlias("Double");
+ this.AddTypeAlias("ByteArray");
this.AddTypeAlias("Guid");
this.AddTypeAlias("DateTime");
this.AddTypeAlias("DateTimeOffset");
this.AddTypeAlias("TimeSpan");
- this.AddTypeAlias("ExpandoObject");
+ this.AddTypeAlias("Stream");
this.AddTypeAlias("JSON");
- this.AddTypeAlias>("StringDictionary");
+ this.AddTypeAlias>("StringDictionary");
+ this.AddTypeAlias>("ObjectDictionary");
this.AddTypeAlias>("StringMap");
this.AddTypeAlias>("ObjectMap");
- this.AddTypeAlias>("ObjectDictionary");
}
/// Gets the type alias dictionary.
diff --git a/src/modules/Elsa.Http/Features/HttpFeature.cs b/src/modules/Elsa.Http/Features/HttpFeature.cs
index defb7df0b..faa8e83bb 100644
--- a/src/modules/Elsa.Http/Features/HttpFeature.cs
+++ b/src/modules/Elsa.Http/Features/HttpFeature.cs
@@ -222,6 +222,11 @@ public class HttpFeature : FeatureBase
Services.Configure(options =>
{
+ options.AddTypeAlias("HttpRequest");
+ options.AddTypeAlias("HttpResponse");
+ options.AddTypeAlias("HttpResponseMessage");
+ options.AddTypeAlias("HttpHeaders");
+ options.AddTypeAlias("RouteData");
options.AddTypeAlias("FormFile");
options.AddTypeAlias("FormFile[]");
options.AddTypeAlias("HttpFile");
diff --git a/src/modules/Elsa.WorkflowContexts/Extensions/WorkflowDefinitionExtensions.cs b/src/modules/Elsa.WorkflowContexts/Extensions/WorkflowContextWorkflowDefinitionExtensions.cs
similarity index 69%
rename from src/modules/Elsa.WorkflowContexts/Extensions/WorkflowDefinitionExtensions.cs
rename to src/modules/Elsa.WorkflowContexts/Extensions/WorkflowContextWorkflowDefinitionExtensions.cs
index 1940aa46d..fc8279df0 100644
--- a/src/modules/Elsa.WorkflowContexts/Extensions/WorkflowDefinitionExtensions.cs
+++ b/src/modules/Elsa.WorkflowContexts/Extensions/WorkflowContextWorkflowDefinitionExtensions.cs
@@ -4,16 +4,16 @@ using Elsa.Workflows.Management.Entities;
// ReSharper disable once CheckNamespace
namespace Elsa.Extensions;
-///
/// Adds extension methods to .
-///
-public static class WorkflowDefinitionExtensions
+public static class WorkflowContextWorkflowDefinitionExtensions
{
///
/// Gets the workflow context provider types that are installed on the workflow definition.
///
/// The workflow definition to get the provider types from.
/// The workflow context provider types.
- public static IEnumerable GetWorkflowContextProviderTypes(this WorkflowDefinition workflowDefinition) =>
- workflowDefinition.CustomProperties.GetOrAdd(Constants.WorkflowContextProviderTypesKey, () => new List());
+ public static IEnumerable GetWorkflowContextProviderTypes(this WorkflowDefinition workflowDefinition)
+ {
+ return workflowDefinition.PropertyBag.GetOrAdd(Constants.WorkflowContextProviderTypesKey, () => new List());
+ }
}
\ No newline at end of file
diff --git a/src/modules/Elsa.WorkflowContexts/Middleware/WorkflowContextActivityExecutionMiddleware.cs b/src/modules/Elsa.WorkflowContexts/Middleware/WorkflowContextActivityExecutionMiddleware.cs
index a288acdb9..7b1cda1bc 100644
--- a/src/modules/Elsa.WorkflowContexts/Middleware/WorkflowContextActivityExecutionMiddleware.cs
+++ b/src/modules/Elsa.WorkflowContexts/Middleware/WorkflowContextActivityExecutionMiddleware.cs
@@ -1,36 +1,38 @@
+using System.Text.Json;
+using Elsa.Expressions.Contracts;
using Elsa.Extensions;
using Elsa.WorkflowContexts.Contracts;
using Elsa.Workflows;
using Elsa.Workflows.Contracts;
using Elsa.Workflows.Pipelines.ActivityExecution;
+using Elsa.Workflows.Serialization.Converters;
+using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
namespace Elsa.WorkflowContexts.Middleware;
-///
/// Middleware that loads and save workflow context into the currently executing workflow using installed workflow context providers.
-///
-public class WorkflowContextActivityExecutionMiddleware : IActivityExecutionMiddleware
+[UsedImplicitly]
+public class WorkflowContextActivityExecutionMiddleware(ActivityMiddlewareDelegate next, IServiceScopeFactory serviceScopeFactory, IWellKnownTypeRegistry wellKnownTypeRegistry) : IActivityExecutionMiddleware
{
- private readonly ActivityMiddlewareDelegate _next;
- private readonly IServiceScopeFactory _serviceScopeFactory;
-
- ///
- /// Constructor.
- ///
- public WorkflowContextActivityExecutionMiddleware(ActivityMiddlewareDelegate next, IServiceScopeFactory serviceScopeFactory)
+ private readonly JsonSerializerOptions _jsonSerializerOptions = new JsonSerializerOptions
{
- _next = next;
- _serviceScopeFactory = serviceScopeFactory;
- }
+ PropertyNameCaseInsensitive = true
+ }.WithConverters(new TypeJsonConverter(wellKnownTypeRegistry));
///
public async ValueTask InvokeAsync(ActivityExecutionContext context)
{
// Check if the workflow contains any workflow context providers.
- if (!context.WorkflowExecutionContext.Workflow.CustomProperties.TryGetValue>(Constants.WorkflowContextProviderTypesKey, out var providerTypes))
+ if (!context.WorkflowExecutionContext.Workflow.PropertyBag.TryGetValue>(Constants.WorkflowContextProviderTypesKey, out var providerTypes, _jsonSerializerOptions))
{
- await _next(context);
+ await next(context);
+ return;
+ }
+
+ if (providerTypes.Count == 0)
+ {
+ await next(context);
return;
}
@@ -40,12 +42,12 @@ public class WorkflowContextActivityExecutionMiddleware : IActivityExecutionMidd
// Is the activity configured to load the context?
foreach (var providerType in providerTypes)
{
- // Is the activity configured to load the context or is this a background execution?
+ // Is the activity configured to load the context, or is this a background execution?
var load = isBackgroundExecution || context.Activity.GetActivityWorkflowContextSettings(providerType).Load;
if (!load) continue;
// Load the context.
- using var scope = _serviceScopeFactory.CreateScope();
+ using var scope = serviceScopeFactory.CreateScope();
var provider = (IWorkflowContextProvider)ActivatorUtilities.GetServiceOrCreateInstance(scope.ServiceProvider, providerType);
var value = await provider.LoadAsync(context.WorkflowExecutionContext);
@@ -54,7 +56,7 @@ public class WorkflowContextActivityExecutionMiddleware : IActivityExecutionMidd
}
// Invoke the next middleware.
- await _next(context);
+ await next(context);
// Invoke each workflow context provider to persists the context.
foreach (var providerType in providerTypes)
@@ -64,7 +66,7 @@ public class WorkflowContextActivityExecutionMiddleware : IActivityExecutionMidd
if (!save) continue;
// Get the loaded value from the workflow execution context.
- using var scope = _serviceScopeFactory.CreateScope();
+ using var scope = serviceScopeFactory.CreateScope();
var value = context.WorkflowExecutionContext.GetWorkflowContext(providerType);
// Save the context.
diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/GetById/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/GetById/Endpoint.cs
index 5211a3b5c..24cf2baf4 100644
--- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/GetById/Endpoint.cs
+++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/GetById/Endpoint.cs
@@ -2,6 +2,7 @@ using Elsa.Abstractions;
using Elsa.Workflows.Management;
using Elsa.Workflows.Management.Filters;
using JetBrains.Annotations;
+using Microsoft.AspNetCore.Builder;
namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.GetById;
@@ -12,6 +13,7 @@ internal class GetById(IWorkflowDefinitionStore store, IWorkflowDefinitionLinker
{
Get("/workflow-definitions/by-id/{id}");
ConfigurePermissions("read:workflow-definitions");
+ Options(x => x.WithName("GetWorkflowDefinitionById"));
}
public override async Task HandleAsync(Request request, CancellationToken cancellationToken)
diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Version/Revert.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Version/Revert.cs
index d025bb567..0d7aef8df 100644
--- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Version/Revert.cs
+++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Version/Revert.cs
@@ -4,6 +4,7 @@ using Elsa.Workflows.Api.Constants;
using Elsa.Workflows.Api.Requirements;
using Elsa.Workflows.Management;
using Elsa.Workflows.Management.Filters;
+using Elsa.Workflows.Management.Models;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authorization;
@@ -46,7 +47,12 @@ internal class RevertVersion(IWorkflowDefinitionManager workflowDefinitionManage
return;
}
- await workflowDefinitionManager.RevertVersionAsync(definitionId, version, cancellationToken);
- await SendOkAsync(cancellationToken);
+ var newDefinition = await workflowDefinitionManager.RevertVersionAsync(definitionId, version, cancellationToken);
+ var newDefinitionSummary = WorkflowDefinitionSummary.FromDefinition(newDefinition);
+
+ await SendCreatedAtAsync("GetWorkflowDefinitionById", new
+ {
+ id = newDefinition.Id
+ }, newDefinitionSummary, cancellation: cancellationToken);
}
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/FilteredList/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/FilteredList/Endpoint.cs
index 2b3c2301d..bbed01935 100644
--- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/FilteredList/Endpoint.cs
+++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/FilteredList/Endpoint.cs
@@ -39,6 +39,7 @@ internal class Get : ElsaEndpoint
{
WorkflowInstanceId = request.WorkflowInstanceId,
ActivityIds = request.Filter?.ActivityIds,
+ ActivityNodeIds = request.Filter?.ActivityNodeIds,
ExcludeActivityTypes = request.Filter?.ExcludedActivityTypes,
EventNames = request.Filter?.EventNames,
};
diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/FilteredList/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/FilteredList/Models.cs
index c9e56f52c..a3cbeb52c 100644
--- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/FilteredList/Models.cs
+++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Journal/FilteredList/Models.cs
@@ -5,45 +5,32 @@ using FastEndpoints;
namespace Elsa.Workflows.Api.Endpoints.WorkflowInstances.Journal.FilteredList;
-///
/// Represents a request for a page of workflow execution log records.
-///
internal class Request
{
- ///
/// The ID of the workflow instance to get the execution log for.
- ///
[BindFrom("id")] public string WorkflowInstanceId { get; set; } = default!;
- ///
/// The filter to apply.
- ///
public JournalFilter? Filter { get; set; }
- ///
/// The zero-based page number to get.
- ///
public int? Page { get; set; }
- ///
/// The size of the page to get.
- ///
public int? PageSize { get; set; }
-
- ///
+
/// The number of records to skip.
- ///
public int? Skip { get; set; }
- ///
/// The number of records to take.
- ///
public int? Take { get; set; }
}
internal class JournalFilter
{
public ICollection? ActivityIds { get; set; }
+ public ICollection? ActivityNodeIds { get; set; }
public ICollection? ExcludedActivityTypes { get; set; }
public ICollection? EventNames { get; set; }
}
diff --git a/src/modules/Elsa.Workflows.Api/Services/StaticWorkflowDefinitionLinker.cs b/src/modules/Elsa.Workflows.Api/Services/StaticWorkflowDefinitionLinker.cs
index da2a3351e..d065b5818 100644
--- a/src/modules/Elsa.Workflows.Api/Services/StaticWorkflowDefinitionLinker.cs
+++ b/src/modules/Elsa.Workflows.Api/Services/StaticWorkflowDefinitionLinker.cs
@@ -32,6 +32,7 @@ public class StaticWorkflowDefinitionLinker(
Outputs = workflowDefinitionModel.Outputs,
Outcomes = workflowDefinitionModel.Outcomes,
CustomProperties = workflowDefinitionModel.CustomProperties,
+ PropertyBag = workflowDefinitionModel.PropertyBag,
IsReadonly = workflowDefinitionModel.IsReadonly,
IsSystem = workflowDefinitionModel.IsSystem,
IsLatest = workflowDefinitionModel.IsLatest,
@@ -99,6 +100,7 @@ public class StaticWorkflowDefinitionLinker(
Outputs = item.Outputs,
Outcomes = item.Outcomes,
CustomProperties = item.CustomProperties,
+ PropertyBag = item.PropertyBag,
IsReadonly = item.IsReadonly,
IsSystem = item.IsSystem,
IsLatest = item.IsLatest,
diff --git a/src/modules/Elsa.Workflows.Core/Activities/Workflow.cs b/src/modules/Elsa.Workflows.Core/Activities/Workflow.cs
index db2033629..a7dcaa324 100644
--- a/src/modules/Elsa.Workflows.Core/Activities/Workflow.cs
+++ b/src/modules/Elsa.Workflows.Core/Activities/Workflow.cs
@@ -1,4 +1,5 @@
using System.ComponentModel;
+using Elsa.Common.Models;
using Elsa.Expressions.Models;
using Elsa.Workflows.Attributes;
using Elsa.Workflows.Contracts;
@@ -30,6 +31,7 @@ public class Workflow : Composite