diff --git a/src/modules/Elsa.Workflows.Core/Activities/Composite.cs b/src/modules/Elsa.Workflows.Core/Activities/Composite.cs
index 6a045573c..e31330e3b 100644
--- a/src/modules/Elsa.Workflows.Core/Activities/Composite.cs
+++ b/src/modules/Elsa.Workflows.Core/Activities/Composite.cs
@@ -82,7 +82,6 @@ public abstract class Composite : Activity, IVariableContainer
/// Override this method to execute custom logic when the composite activity completes.
///
/// The context of the composite activity.
- /// The context of the child activity that completed.
protected virtual ValueTask OnCompletedAsync(ActivityCompletedContext context)
{
OnCompleted(context);
@@ -93,7 +92,6 @@ public abstract class Composite : Activity, IVariableContainer
/// Override this method to execute custom logic when the composite activity completes.
///
/// The context of the composite activity.
- /// The context of the child activity that completed.
protected virtual void OnCompleted(ActivityCompletedContext context)
{
}
diff --git a/src/modules/Elsa.Workflows.Core/Models/OutputDescriptor.cs b/src/modules/Elsa.Workflows.Core/Models/OutputDescriptor.cs
index 617deeff4..6021a0d16 100644
--- a/src/modules/Elsa.Workflows.Core/Models/OutputDescriptor.cs
+++ b/src/modules/Elsa.Workflows.Core/Models/OutputDescriptor.cs
@@ -20,13 +20,16 @@ public class OutputDescriptor : PropertyDescriptor
string displayName,
Type type,
Func valueGetter,
- string? description = default,
+ Action valueSetter,
+
+ string? description = default,
bool? isBrowsable = default)
{
Name = name;
DisplayName = displayName;
Type = type;
ValueGetter = valueGetter;
+ ValueSetter = valueSetter;
Description = description;
IsBrowsable = isBrowsable;
}
diff --git a/src/modules/Elsa.Workflows.Core/Services/ActivityDescriber.cs b/src/modules/Elsa.Workflows.Core/Services/ActivityDescriber.cs
index 91117cc4f..ecb1d1c43 100644
--- a/src/modules/Elsa.Workflows.Core/Services/ActivityDescriber.cs
+++ b/src/modules/Elsa.Workflows.Core/Services/ActivityDescriber.cs
@@ -65,7 +65,7 @@ public class ActivityDescriber : IActivityDescriber
Name = x,
DisplayName = x
}).ToDictionary(x => x.Name) ?? new Dictionary();
-
+
var allPorts = embeddedPorts.Concat(flowPorts.Values);
var inputProperties = GetInputProperties(activityType).ToList();
var outputProperties = GetOutputProperties(activityType).ToList();
@@ -96,16 +96,16 @@ public class ActivityDescriber : IActivityDescriber
return activity;
}
};
-
+
return descriptor;
}
///
- public IEnumerable GetInputProperties([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type activityType) =>
+ public IEnumerable GetInputProperties([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type activityType) =>
activityType.GetProperties().Where(x => typeof(Input).IsAssignableFrom(x.PropertyType) || x.GetCustomAttribute() != null).DistinctBy(x => x.Name);
///
- public IEnumerable GetOutputProperties([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type activityType) =>
+ public IEnumerable GetOutputProperties([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type activityType) =>
activityType.GetProperties().Where(x => typeof(Output).IsAssignableFrom(x.PropertyType)).DistinctBy(x => x.Name).ToList();
///
@@ -122,6 +122,7 @@ public class ActivityDescriber : IActivityDescriber
outputAttribute?.DisplayName ?? propertyInfo.Name.Humanize(LetterCasing.Title),
wrappedPropertyType,
propertyInfo.GetValue,
+ propertyInfo.SetValue,
descriptionAttribute?.Description ?? outputAttribute?.Description,
outputAttribute?.IsBrowsable ?? true
));
@@ -140,7 +141,7 @@ public class ActivityDescriber : IActivityDescriber
wrappedPropertyType = wrappedPropertyType.GetTypeOfNullable();
var inputOptions = await _optionsResolver.GetOptionsAsync(propertyInfo, cancellationToken);
-
+
return new InputDescriptor
(
inputAttribute?.Name ?? propertyInfo.Name,
@@ -156,21 +157,20 @@ public class ActivityDescriber : IActivityDescriber
inputAttribute?.Order ?? 0,
_defaultValueResolver.GetDefaultValue(propertyInfo),
inputAttribute?.DefaultSyntax,
- //inputAttribute?.SupportedSyntaxes, TODO: Come up with a different way to specify support languages for activity inputs. By default, maybe all props should support all registered scripting languages?
inputAttribute?.IsReadOnly ?? false,
inputAttribute?.IsBrowsable ?? true
);
}
///
- public async Task> DescribeInputPropertiesAsync([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]Type activityType, CancellationToken cancellationToken = default)
+ public async Task> DescribeInputPropertiesAsync([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type activityType, CancellationToken cancellationToken = default)
{
var properties = GetInputProperties(activityType);
return await DescribeInputPropertiesAsync(properties, cancellationToken);
}
///
- public async Task> DescribeOutputPropertiesAsync([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]Type activityType, CancellationToken cancellationToken = default) =>
+ public async Task> DescribeOutputPropertiesAsync([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type activityType, CancellationToken cancellationToken = default) =>
await DescribeOutputPropertiesAsync(GetOutputProperties(activityType), cancellationToken);
private async Task> DescribeInputPropertiesAsync(IEnumerable properties, CancellationToken cancellationToken = default)
diff --git a/src/modules/Elsa.Workflows.Management/Activities/SetOutput/SetOutput.cs b/src/modules/Elsa.Workflows.Management/Activities/SetOutput/SetOutput.cs
index 1b611b9c7..3a4afa5ed 100644
--- a/src/modules/Elsa.Workflows.Management/Activities/SetOutput/SetOutput.cs
+++ b/src/modules/Elsa.Workflows.Management/Activities/SetOutput/SetOutput.cs
@@ -1,6 +1,7 @@
using System.Runtime.CompilerServices;
using Elsa.Extensions;
using Elsa.Workflows.Core;
+using Elsa.Workflows.Core.Activities;
using Elsa.Workflows.Core.Attributes;
using Elsa.Workflows.Core.Models;
using JetBrains.Annotations;
@@ -18,7 +19,7 @@ public class SetOutput : CodeActivity
public SetOutput([CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : base(source, line)
{
}
-
+
///
/// The name of the output to assign.
///
@@ -68,9 +69,19 @@ public class SetOutput : CodeActivity
{
// If this activity executes in a composite activity, we need to update the composite activity's output variable as well.
var variable = context.ExpressionExecutionContext.GetVariable(outputName);
-
- if(variable != null)
+
+ if (variable != null)
context.Set(variable, outputValue);
+
+ // Also set the output on the composite activity's output property.
+ var compositeActivityContext = ancestorContext.ParentActivityExecutionContext;
+ var compositeActivity = compositeActivityContext.Activity;
+ var compositeActivityDescriptor = compositeActivityContext.ActivityDescriptor;
+ var compositeOutputDescriptor = compositeActivityDescriptor.Outputs.FirstOrDefault(x => x.Name == outputName);
+ var compositeOutput = (Output?)compositeOutputDescriptor?.ValueGetter(compositeActivity);
+
+ if(compositeOutput != null)
+ ancestorContext.ParentActivityExecutionContext.Set(compositeOutput, outputValue);
}
}
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/WorkflowDefinitionActivityProvider.cs b/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/WorkflowDefinitionActivityProvider.cs
index d64b733b5..73f7bfc95 100644
--- a/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/WorkflowDefinitionActivityProvider.cs
+++ b/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/WorkflowDefinitionActivityProvider.cs
@@ -32,10 +32,10 @@ public class WorkflowDefinitionActivityProvider : IActivityProvider
{
var filter = new WorkflowDefinitionFilter
{
- UsableAsActivity = true,
+ UsableAsActivity = true,
VersionOptions = VersionOptions.All
};
-
+
var definitions = (await _store.FindManyAsync(filter, cancellationToken)).ToList();
var descriptors = CreateDescriptors(definitions);
return descriptors;
@@ -47,7 +47,7 @@ public class WorkflowDefinitionActivityProvider : IActivityProvider
private ActivityDescriptor CreateDescriptor(WorkflowDefinition definition, ICollection allDefinitions)
{
var typeName = definition.Name!.Pascalize();
-
+
var latestPublishedVersion = allDefinitions
.Where(x => x.DefinitionId == definition.DefinitionId && x.IsPublished)
.MaxBy(x => x.Version);
@@ -59,7 +59,7 @@ public class WorkflowDefinitionActivityProvider : IActivityProvider
IsBrowsable = true,
Type = PortType.Flow
}).ToList();
-
+
var rootPort = new Port
{
Name = nameof(WorkflowDefinitionActivity.Root),
@@ -67,7 +67,7 @@ public class WorkflowDefinitionActivityProvider : IActivityProvider
IsBrowsable = true,
Type = PortType.Embedded
};
-
+
ports.Insert(0, rootPort);
return new ActivityDescriptor