diff --git a/src/modules/Elsa.Workflows.Api/Contracts/IWorkflowInstanceExportNameProvider.cs b/src/modules/Elsa.Workflows.Api/Contracts/IWorkflowInstanceExportNameProvider.cs
new file mode 100644
index 000000000..12d510470
--- /dev/null
+++ b/src/modules/Elsa.Workflows.Api/Contracts/IWorkflowInstanceExportNameProvider.cs
@@ -0,0 +1,18 @@
+using Elsa.Workflows.Management.Entities;
+
+namespace Elsa.Workflows.Api;
+
+///
+/// Defines a contract for generating a filename suitable for exporting a workflow instance.
+///
+public interface IWorkflowInstanceExportNameProvider
+{
+ ///
+ /// Generates a filename for a workflow instance export.
+ ///
+ /// The workflow instance being exported.
+ /// The export model representing the instance (optional).
+ /// Cancellation token.
+ /// A filename safe for saving to disk.
+ Task GetFileNameAsync(WorkflowInstance instance, object model, CancellationToken cancellationToken = default);
+}
diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Export/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Export/Endpoint.cs
index 1b0e85a1a..2b695ff11 100644
--- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Export/Endpoint.cs
+++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowInstances/Export/Endpoint.cs
@@ -31,6 +31,7 @@ internal class Export : ElsaEndpointWithMapper
private readonly IWorkflowStateSerializer _workflowStateSerializer;
private readonly IPayloadSerializer _payloadSerializer;
private readonly ISafeSerializer _safeSerializer;
+ private readonly IWorkflowInstanceExportNameProvider _workFlowInstanceExportNameProvider;
///
public Export(
@@ -40,7 +41,8 @@ internal class Export : ElsaEndpointWithMapper
IBookmarkStore bookmarkStore,
IWorkflowStateSerializer workflowStateSerializer,
IPayloadSerializer payloadSerializer,
- ISafeSerializer safeSerializer)
+ ISafeSerializer safeSerializer,
+ IWorkflowInstanceExportNameProvider workFlowInstanceExportNameProvider)
{
_workflowInstanceStore = workflowInstanceStore;
_activityExecutionStore = activityExecutionStore;
@@ -49,6 +51,7 @@ internal class Export : ElsaEndpointWithMapper
_workflowStateSerializer = workflowStateSerializer;
_payloadSerializer = payloadSerializer;
_safeSerializer = safeSerializer;
+ _workFlowInstanceExportNameProvider = workFlowInstanceExportNameProvider;
}
///
@@ -85,7 +88,9 @@ internal class Export : ElsaEndpointWithMapper
{
var model = await CreateExportModelAsync(request, instance, cancellationToken);
var binaryJson = SerializeWorkflowInstance(model);
- var fileName = GetFileName(instance.WorkflowState);
+
+ var fileName = await _workFlowInstanceExportNameProvider.GetFileNameAsync(instance, model, cancellationToken);
+
var entry = zipArchive.CreateEntry(fileName, CompressionLevel.Optimal);
await using var entryStream = entry.Open();
await entryStream.WriteAsync(binaryJson, cancellationToken);
@@ -109,7 +114,7 @@ internal class Export : ElsaEndpointWithMapper
var model = await CreateExportModelAsync(request, instance, cancellationToken);
var binaryJson = SerializeWorkflowInstance(model);
- var fileName = GetFileName(instance.WorkflowState);
+ var fileName = await _workFlowInstanceExportNameProvider.GetFileNameAsync(instance, model, cancellationToken);
await Send.BytesAsync(binaryJson, fileName, cancellation: cancellationToken);
}
@@ -168,12 +173,6 @@ internal class Export : ElsaEndpointWithMapper
return page.Items;
}
- private static string GetFileName(WorkflowState instance)
- {
- var fileName = $"workflow-instance-{instance.Id.ToLowerInvariant()}.json";
- return fileName;
- }
-
private static byte[] SerializeWorkflowInstance(ExportedWorkflowState model)
{
var binaryJson = JsonSerializer.SerializeToUtf8Bytes(model);
diff --git a/src/modules/Elsa.Workflows.Api/Features/WorkflowsApiFeature.cs b/src/modules/Elsa.Workflows.Api/Features/WorkflowsApiFeature.cs
index 721a36827..fd625fc05 100644
--- a/src/modules/Elsa.Workflows.Api/Features/WorkflowsApiFeature.cs
+++ b/src/modules/Elsa.Workflows.Api/Features/WorkflowsApiFeature.cs
@@ -41,5 +41,6 @@ public class WorkflowsApiFeature(IModule module) : FeatureBase(module)
{
options.AddPolicy(AuthorizationPolicies.NotReadOnlyPolicy, policy => policy.AddRequirements(new NotReadOnlyRequirement()));
});
+ Services.AddScoped();
}
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Api/Providers/DefaultWorkflowInstanceExportNameProvider.cs b/src/modules/Elsa.Workflows.Api/Providers/DefaultWorkflowInstanceExportNameProvider.cs
new file mode 100644
index 000000000..76728e26e
--- /dev/null
+++ b/src/modules/Elsa.Workflows.Api/Providers/DefaultWorkflowInstanceExportNameProvider.cs
@@ -0,0 +1,15 @@
+using Elsa.Workflows.Management.Entities;
+
+namespace Elsa.Workflows.Api;
+
+///
+/// Provides a default implementation for generating export file names for workflow instances.
+///
+public class DefaultWorkflowInstanceExportNameProvider : IWorkflowInstanceExportNameProvider
+{
+ public Task GetFileNameAsync(WorkflowInstance instance, object model, CancellationToken cancellationToken = default)
+ {
+ var fileName = $"workflow-instance-{instance.Id.ToLowerInvariant()}.json";
+ return Task.FromResult(fileName);
+ }
+}