Add dynamic activity provider sample project
This commit is contained in:
parent
78f01f267b
commit
94904160a9
7
Elsa.sln
7
Elsa.sln
|
|
@ -230,6 +230,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.AspNet.MongoDb
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Workflows.Api.Rpc", "src\modules\Elsa.Workflows.Api.Rpc\Elsa.Workflows.Api.Rpc.csproj", "{0A94D69A-61AC-4654-83AB-B24445628A99}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.AspNet.DynamicActivityProvider", "src\samples\aspnet\Elsa.Samples.AspNet.DynamicActivityProvider\Elsa.Samples.AspNet.DynamicActivityProvider.csproj", "{85E13383-7C39-4719-AAC0-0B357C3A97C7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -576,6 +578,10 @@ Global
|
|||
{0A94D69A-61AC-4654-83AB-B24445628A99}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0A94D69A-61AC-4654-83AB-B24445628A99}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0A94D69A-61AC-4654-83AB-B24445628A99}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{85E13383-7C39-4719-AAC0-0B357C3A97C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{85E13383-7C39-4719-AAC0-0B357C3A97C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{85E13383-7C39-4719-AAC0-0B357C3A97C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{85E13383-7C39-4719-AAC0-0B357C3A97C7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{155227F0-A33B-40AA-A4B4-06F813EB921B} = {61017E64-6D00-49CB-9E81-5002DC8F7D5F}
|
||||
|
|
@ -680,5 +686,6 @@ Global
|
|||
{3A377A6A-F735-4010-9E00-72E8BEB8F1F2} = {9B4F139F-7D26-435C-A561-89E65A67A8E5}
|
||||
{DAACE93A-866E-428E-B2A9-AFAC79F9C7A4} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5}
|
||||
{0A94D69A-61AC-4654-83AB-B24445628A99} = {B08B4E00-C2AB-48F3-8389-449F42AEF179}
|
||||
{85E13383-7C39-4719-AAC0-0B357C3A97C7} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -0,0 +1,161 @@
|
|||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Http;
|
||||
using Elsa.Samples.AspNet.DynamicActivityProvider.Models;
|
||||
using Elsa.Workflows.Core;
|
||||
using Elsa.Workflows.Core.Contracts;
|
||||
using Elsa.Workflows.Core.Models;
|
||||
using Elsa.Workflows.Management.Extensions;
|
||||
using Humanizer;
|
||||
|
||||
namespace Elsa.Samples.AspNet.DynamicActivityProvider.ActivityProviders;
|
||||
|
||||
/// <summary>
|
||||
/// Provides activities based on API descriptions (see /Data/apis.json).
|
||||
/// </summary>
|
||||
public class ApiActivityProvider : IActivityProvider
|
||||
{
|
||||
private readonly IActivityFactory _activityFactory;
|
||||
private readonly IActivityDescriber _activityDescriber;
|
||||
|
||||
public ApiActivityProvider(IActivityFactory activityFactory, IActivityDescriber activityDescriber)
|
||||
{
|
||||
_activityFactory = activityFactory;
|
||||
_activityDescriber = activityDescriber;
|
||||
}
|
||||
|
||||
public async ValueTask<IEnumerable<ActivityDescriptor>> GetDescriptorsAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
// Read JSON file.
|
||||
var json = await File.ReadAllTextAsync("Data/apis.json", cancellationToken);
|
||||
|
||||
// Parse JSON into a list of API definitions.
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
};
|
||||
|
||||
var apisDefinitions = JsonSerializer.Deserialize<ApiDefinition[]>(json, options)!;
|
||||
|
||||
// Create activity descriptors from API definitions.
|
||||
var activities = ((await Task.WhenAll(apisDefinitions.Select(async x => await CreateActivityDescriptors(x, cancellationToken)))).SelectMany(x => x)).ToList();
|
||||
|
||||
// Return activity descriptors.
|
||||
return activities;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates activity descriptors from an API definition's endpoints.
|
||||
/// </summary>
|
||||
/// <param name="api">The API definition containing the endpoints.</param>
|
||||
/// <param name="cancellationToken">An optional cancellation token.</param>
|
||||
/// <returns>A list of activity descriptors.</returns>
|
||||
private async Task<IEnumerable<ActivityDescriptor>> CreateActivityDescriptors(ApiDefinition api, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var descriptorTasks = api.Endpoints.Select(async endpoint => await CreateActivityDescriptorFromEndpointAsync(api, endpoint, cancellationToken)).ToList();
|
||||
|
||||
return await Task.WhenAll(descriptorTasks);
|
||||
}
|
||||
|
||||
private async Task<ActivityDescriptor> CreateActivityDescriptorFromEndpointAsync(ApiDefinition api, ApiEndpointDefinition endpoint, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// Create a fully qualified type name for the activity ("{namespace}.{apiName}.{endpointName}").
|
||||
var fullTypeName = $"Demo.{api.Name}.{endpoint.Name}";
|
||||
|
||||
// ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract
|
||||
// Justification: the JSON input may not have a parameters property.
|
||||
var parameters = endpoint.Parameters ?? new List<ApiParameterDefinition>();
|
||||
|
||||
// Create inputs from endpoint parameters.
|
||||
var inputs = parameters.Select(CreateInputDescriptor).ToList();
|
||||
|
||||
// Create inputs for the URL and method properties of the SendHttpRequest activity, which will be used as the implementation for executing instances of this activity.
|
||||
// They are set in the constructor, and should not be visible to the user.
|
||||
var urlInputDescriptor = await _activityDescriber.DescribeInputPropertyAsync<SendHttpRequest, Input<Uri?>>(x => x.Url, cancellationToken);
|
||||
var urlInputReferenceId = Guid.NewGuid().ToString();
|
||||
var methodInputDescriptor = await _activityDescriber.DescribeInputPropertyAsync<SendHttpRequest, Input<string>>(x => x.Method, cancellationToken);
|
||||
var methodInputReferenceId = Guid.NewGuid().ToString();
|
||||
|
||||
urlInputDescriptor.IsBrowsable = false;
|
||||
urlInputDescriptor.ValueGetter = activity =>
|
||||
{
|
||||
var input = new Input<Uri>(context =>
|
||||
{
|
||||
// Replace path parameters with input values.
|
||||
var pathBuilder = new StringBuilder(endpoint.Path);
|
||||
|
||||
foreach (var parameter in parameters)
|
||||
{
|
||||
var inputDescriptor = inputs.FirstOrDefault(x => x.Name == parameter.Name);
|
||||
var inputValue = inputDescriptor?.ValueGetter(activity) is Input inputValueInput ? context.Get(inputValueInput.MemoryBlockReference()) : default;
|
||||
pathBuilder.Replace("{" + parameter.Name + "}", inputValue?.ToString());
|
||||
}
|
||||
|
||||
return new(new Uri(api.BaseUrl, pathBuilder.ToString()));
|
||||
}, urlInputReferenceId);
|
||||
return input;
|
||||
};
|
||||
|
||||
methodInputDescriptor.IsBrowsable = false;
|
||||
methodInputDescriptor.ValueGetter = _ => new Input<string>(endpoint.Method, methodInputReferenceId);
|
||||
|
||||
inputs.Add(urlInputDescriptor);
|
||||
inputs.Add(methodInputDescriptor);
|
||||
|
||||
// Create an output descriptor based on the send HTTP request activity's ParsedContent property.
|
||||
var outputDescriptor = await _activityDescriber.DescribeOutputProperty<SendHttpRequest, Output<object?>>(x => x.ParsedContent, cancellationToken);
|
||||
|
||||
return new ActivityDescriptor
|
||||
{
|
||||
Kind = ActivityKind.Task,
|
||||
Category = "Demo",
|
||||
Description = endpoint.Description,
|
||||
Name = endpoint.Name,
|
||||
TypeName = fullTypeName,
|
||||
Namespace = $"Api.{api.Name}",
|
||||
DisplayName = endpoint.Name.Humanize(),
|
||||
Inputs = inputs,
|
||||
Outputs = new[] { outputDescriptor },
|
||||
Constructor = context =>
|
||||
{
|
||||
// The constructor is called when an activity instance of this type is requested.
|
||||
|
||||
// Create the activity instance.
|
||||
var activity = _activityFactory.Create<SendHttpRequest>(context);
|
||||
|
||||
// Customize the activity type name.
|
||||
activity.Type = fullTypeName;
|
||||
|
||||
// Configure the activity's URL and method properties.
|
||||
activity.Url = new Input<Uri?>(new ReadReference(urlInputReferenceId));
|
||||
activity.Method = new(new ReadReference(methodInputReferenceId));
|
||||
|
||||
return activity;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an input descriptor from an API parameter definition.
|
||||
/// </summary>
|
||||
/// <param name="parameter">The API parameter definition.</param>
|
||||
private static InputDescriptor CreateInputDescriptor(ApiParameterDefinition parameter)
|
||||
{
|
||||
var inputDescriptor = new InputDescriptor
|
||||
{
|
||||
Description = parameter.Description,
|
||||
DefaultValue = parameter.DefaultValue,
|
||||
Type = parameter.Type == "number" ? typeof(int) : typeof(string),
|
||||
Name = parameter.Name,
|
||||
DisplayName = parameter.Name.Humanize(),
|
||||
IsSynthetic = true, // This is a synthetic property, i.e. it is not part of the activity's .NET type.
|
||||
IsWrapped = true, // This property is wrapped within an Input<T> object.
|
||||
UIHint = InputUIHints.SingleLine,
|
||||
ValueGetter = activity => activity.SyntheticProperties.GetValueOrDefault(parameter.Name),
|
||||
ValueSetter = (activity, value) => activity.SyntheticProperties[parameter.Name] = value!,
|
||||
};
|
||||
return inputDescriptor;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
[{
|
||||
"name": "Reqres",
|
||||
"baseUrl": "https://reqres.in",
|
||||
"endpoints": [
|
||||
{
|
||||
"name": "GetUsers",
|
||||
"path": "/api/users",
|
||||
"method": "GET",
|
||||
"description": "Get all users"
|
||||
},
|
||||
{
|
||||
"name": "GetUser",
|
||||
"path": "/api/users/{UserId}",
|
||||
"method": "GET",
|
||||
"description": "Get a user",
|
||||
"params": [
|
||||
{
|
||||
"name": "UserId",
|
||||
"type": "number",
|
||||
"description": "User id"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "CreateUser",
|
||||
"path": "/api/users",
|
||||
"method": "POST",
|
||||
"description": "Create a user",
|
||||
"params": [
|
||||
{
|
||||
"name": "UserName",
|
||||
"type": "string",
|
||||
"description": "User name"
|
||||
},
|
||||
{
|
||||
"name": "Job",
|
||||
"type": "string",
|
||||
"description": "User job"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}]
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\bundles\Elsa\Elsa.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.Http\Elsa.Http.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.Identity\Elsa.Identity.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.JavaScript\Elsa.JavaScript.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.Liquid\Elsa.Liquid.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.EntityFrameworkCore.Sqlite\Elsa.EntityFrameworkCore.Sqlite.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.EntityFrameworkCore\Elsa.EntityFrameworkCore.csproj" />
|
||||
<ProjectReference Include="..\..\..\modules\Elsa.Workflows.Api\Elsa.Workflows.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="Data\apis.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Workflows\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
namespace Elsa.Samples.AspNet.DynamicActivityProvider.Models;
|
||||
|
||||
public record ApiDefinition(string Name, Uri BaseUrl, ICollection<ApiEndpointDefinition> Endpoints);
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Elsa.Samples.AspNet.DynamicActivityProvider.Models;
|
||||
|
||||
public record ApiEndpointDefinition(
|
||||
string Name,
|
||||
string Description,
|
||||
string Path,
|
||||
string Method,
|
||||
[property: JsonPropertyName("params")] ICollection<ApiParameterDefinition> Parameters);
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
namespace Elsa.Samples.AspNet.DynamicActivityProvider.Models;
|
||||
|
||||
public record ApiParameterDefinition(string Name, string Type, string Description, string? DefaultValue);
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
using Elsa.EntityFrameworkCore.Modules.Identity;
|
||||
using Elsa.EntityFrameworkCore.Modules.Management;
|
||||
using Elsa.EntityFrameworkCore.Modules.Runtime;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Samples.AspNet.DynamicActivityProvider.ActivityProviders;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var services = builder.Services;
|
||||
|
||||
// Add Elsa services.
|
||||
services.AddElsa(elsa => elsa
|
||||
// Expose API endpoints.
|
||||
.UseWorkflowsApi()
|
||||
|
||||
.UseWorkflowManagement(management => management.UseEntityFrameworkCore())
|
||||
.UseWorkflowRuntime(runtime => runtime.UseEntityFrameworkCore())
|
||||
|
||||
// Configure identity so that we can create a default admin user.
|
||||
.UseIdentity(identity =>
|
||||
{
|
||||
identity.UseAdminUserProvider();
|
||||
identity.UseEntityFrameworkCore();
|
||||
identity.TokenOptions = options =>
|
||||
{
|
||||
options.SigningKey = "secret-token-signing-key";
|
||||
options.AccessTokenLifetime = TimeSpan.FromDays(1);
|
||||
};
|
||||
})
|
||||
|
||||
// HTTP workflows.
|
||||
.UseHttp()
|
||||
|
||||
// Use default authentication (JWT).
|
||||
.UseDefaultAuthentication(auth => auth.UseAdminApiKey())
|
||||
);
|
||||
|
||||
// Add custom activity provider.
|
||||
services.AddActivityProvider<ApiActivityProvider>();
|
||||
|
||||
services.AddCors(cors => cors.AddDefaultPolicy(policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()));
|
||||
|
||||
// Configure middleware pipeline.
|
||||
var app = builder.Build();
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
app.UseDeveloperExceptionPage();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
app.UseCors();
|
||||
app.UseWorkflowsApi();
|
||||
app.UseWorkflows();
|
||||
app.Run();
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:41572",
|
||||
"sslPort": 44398
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5015",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7145;http://localhost:5015",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
# Dynamic Activity Providers
|
||||
|
||||
This sample project demonstrates how to implement a dynamic activity provider.
|
||||
|
||||
## Overview
|
||||
|
||||
The key to providing activities dynamically to the activity registry is to implement the `IActivityProvider` interface. This interface defines a single method, `GetDescriptorsAsync`, which returns a list of activity descriptors.
|
||||
|
||||
In this example, we are loading API endpoint definitions from a JSON file located in the `Data` folder and create an activity descriptor for each endpoint.
|
||||
The activity descriptor is then used to create an activity type, which is then registered with the activity registry.
|
||||
|
||||
This example could be applied to any other data source, such as a database or a web service, Open API specifications, GraphQL, etc.
|
||||
|
||||
## Usage
|
||||
|
||||
1. Run the sample project.
|
||||
2. Open the workflow editor.
|
||||
3. Notice the new activities in the toolbox.
|
||||
4. Drag one of the new activities onto the canvas.
|
||||
5. Notice the new activity in the canvas.
|
||||
6. Run the workflow.
|
||||
7. Notice the new activity being executed.
|
||||
|
||||
## Notes
|
||||
|
||||
This project provides sample workflows that you can import into the workflow editor. The workflows are located in the `Workflows` folder.
|
||||
You can then use the workflow editor to inspect the workflows and see how the activities are used.
|
||||
When imported, you can invoke the workflows using the sample-request.http file located in the root folder containing this project.
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
{
|
||||
"id": "0ad67e344f664e4ba40430933db6383d",
|
||||
"definitionId": "2a29bd086ba047ad82c296f380b2b21d",
|
||||
"name": "Create User",
|
||||
"createdAt": "2023-07-13T14:06:07.932781+00:00",
|
||||
"version": 9,
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"options": {
|
||||
"autoUpdateConsumingWorkflows": false
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "Flowchart1",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"NotFoundConnectionsKey": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"start": "HttpEndpoint1",
|
||||
"activities": [
|
||||
{
|
||||
"path": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "/users"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "540fb073-7da0-40e4-affd-7d12b83bd41b"
|
||||
}
|
||||
},
|
||||
"supportedMethods": {
|
||||
"typeName": "String[]",
|
||||
"expression": {
|
||||
"type": "Object",
|
||||
"value": "[\u0022POST\u0022]"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "cd84bc03-5395-449b-96eb-27d5ad17ca53"
|
||||
}
|
||||
},
|
||||
"authorize": {
|
||||
"typeName": "Boolean",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "False"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "HttpEndpoint1:input-1"
|
||||
}
|
||||
},
|
||||
"policy": null,
|
||||
"parsedContent": {
|
||||
"typeName": "Object",
|
||||
"memoryReference": {
|
||||
"id": "0a9e4d85af2149119068e324e3e61e32"
|
||||
}
|
||||
},
|
||||
"routeData": null,
|
||||
"queryStringData": null,
|
||||
"headers": null,
|
||||
"result": null,
|
||||
"id": "HttpEndpoint1",
|
||||
"name": null,
|
||||
"type": "Elsa.HttpEndpoint",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": true,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 120,
|
||||
"y": 260
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"statusCode": {
|
||||
"typeName": "System.Net.HttpStatusCode, System.Net.Primitives",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "OK"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteHttpResponse1:input-1"
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"typeName": "Object",
|
||||
"expression": {
|
||||
"type": "JavaScript",
|
||||
"value": "getParsedContentFromCreateUser1()"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "457df76f-3bdd-4e7e-ba8a-10ebed80281d"
|
||||
}
|
||||
},
|
||||
"contentType": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "application/json"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "4673dc8b-e2ee-48c2-8b7a-5c3e2c3a7560"
|
||||
}
|
||||
},
|
||||
"responseHeaders": {
|
||||
"typeName": "Elsa.Http.Models.HttpResponseHeaders, Elsa.Http",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "{}"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteHttpResponse1:input-2"
|
||||
}
|
||||
},
|
||||
"id": "WriteHttpResponse1",
|
||||
"name": null,
|
||||
"type": "Elsa.WriteHttpResponse",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 640,
|
||||
"y": 260
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"expectedStatusCodes": [],
|
||||
"unmatchedStatusCode": null,
|
||||
"url": {
|
||||
"typeName": "System.Uri, System.Private.Uri",
|
||||
"memoryReference": {
|
||||
"id": "44cb8368-b578-4b02-beb7-cbac55359ab6"
|
||||
}
|
||||
},
|
||||
"method": {
|
||||
"typeName": "String",
|
||||
"memoryReference": {
|
||||
"id": "d39ebcb9-8943-4d76-8299-7761aef1f8e3"
|
||||
}
|
||||
},
|
||||
"content": null,
|
||||
"contentType": null,
|
||||
"authorization": null,
|
||||
"requestHeaders": {
|
||||
"typeName": "Elsa.Http.Models.HttpRequestHeaders, Elsa.Http",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "{}"
|
||||
},
|
||||
"memoryReference": {}
|
||||
},
|
||||
"parsedContent": null,
|
||||
"result": null,
|
||||
"id": "CreateUser1",
|
||||
"name": null,
|
||||
"type": "Demo.Reqres.CreateUser",
|
||||
"version": 0,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 428,
|
||||
"y": 255
|
||||
}
|
||||
}
|
||||
},
|
||||
"userName": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "JavaScript",
|
||||
"value": "getParsedContentFromHttpEndpoint1().user;"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "14ebd00e-bd1a-4953-a933-d49439ed418c"
|
||||
}
|
||||
},
|
||||
"job": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "JavaScript",
|
||||
"value": "getParsedContentFromHttpEndpoint1().job;"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "e92af470-3d83-4891-96b4-e83331d0896e"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": {
|
||||
"activity": "HttpEndpoint1",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "CreateUser1",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "CreateUser1",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "WriteHttpResponse1",
|
||||
"port": "In"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"id":"906cd28a12454b06b71bb724cd5891d0","definitionId":"4b3bbe91862c42ba921e21f70b429d8e","name":"Get Users","createdAt":"2023-07-13T14:02:19.276895+00:00","version":20,"variables":[{"id":"c4c6fbc0926f40d7a93e61eb7668b40b","name":"Users","typeName":"Object","isArray":true,"storageDriverTypeName":"Elsa.Workflows.Core.Services.WorkflowStorageDriver, Elsa.Workflows.Core"}],"inputs":[],"outputs":[],"outcomes":[],"customProperties":{},"isReadonly":false,"isLatest":true,"isPublished":false,"options":{"autoUpdateConsumingWorkflows":false},"root":{"type":"Elsa.Flowchart","version":1,"id":"Flowchart1","metadata":{},"customProperties":{"NotFoundConnectionsKey":[],"canStartWorkflow":false,"runAsynchronously":false},"start":"HttpEndpoint1","activities":[{"path":{"typeName":"String","expression":{"type":"Literal","value":"users/all"},"memoryReference":{"id":"6f30b933-ed1c-47fb-9d13-7b50f425e806"}},"supportedMethods":{"typeName":"String[]","expression":{"type":"Object","value":"[\u0022GET\u0022]"},"memoryReference":{"id":"d7ee590e-02b4-485d-8730-cc8656c55a99"}},"authorize":{"typeName":"Boolean","expression":{"type":"Literal","value":"False"},"memoryReference":{"id":"HttpEndpoint1:input-1"}},"policy":{"typeName":"String","expression":{"type":"Literal"},"memoryReference":{"id":"HttpEndpoint1:input-2"}},"parsedContent":null,"routeData":null,"queryStringData":null,"headers":null,"result":null,"id":"HttpEndpoint1","name":null,"type":"Elsa.HttpEndpoint","version":1,"customProperties":{"canStartWorkflow":true,"runAsynchronously":false},"metadata":{"designer":{"position":{"x":120,"y":260}}}},{"statusCode":{"typeName":"System.Net.HttpStatusCode, System.Net.Primitives","expression":{"type":"Literal","value":"OK"},"memoryReference":{"id":"WriteHttpResponse1:input-1"}},"content":{"typeName":"Object","expression":{"type":"JavaScript","value":"const users = getUsers();\nreturn users;"},"memoryReference":{"id":"09552413-74b1-4156-86a3-6679feeec83e"}},"contentType":{"typeName":"String","expression":{"type":"Literal","value":"application/json"},"memoryReference":{"id":"a7b8ff37-34a3-4400-88b2-026f19de8901"}},"responseHeaders":{"typeName":"Elsa.Http.Models.HttpResponseHeaders, Elsa.Http","expression":{"type":"Literal","value":"{}"},"memoryReference":{"id":"WriteHttpResponse1:input-2"}},"id":"WriteHttpResponse1","name":null,"type":"Elsa.WriteHttpResponse","version":1,"customProperties":{"canStartWorkflow":false,"runAsynchronously":false},"metadata":{"designer":{"position":{"x":920,"y":260}}}},{"variable":{"id":"c4c6fbc0926f40d7a93e61eb7668b40b","name":"Users","typeName":"Object","value":"","storageDriverTypeName":"Elsa.Workflows.Core.Services.WorkflowStorageDriver, Elsa.Workflows.Core"},"value":{"typeName":"Object","expression":{"type":"JavaScript","value":"getParsedContentFromGetUsers1()"},"memoryReference":{"id":"b1f4ed34-25d8-42f4-a59b-03541b11bfa6"}},"id":"SetVariable1","name":null,"type":"Elsa.SetVariable","version":1,"customProperties":{"canStartWorkflow":false,"runAsynchronously":false},"metadata":{"designer":{"position":{"x":660,"y":260}},"displayText":"Set Users"}},{"expectedStatusCodes":[],"unmatchedStatusCode":null,"url":{"typeName":"System.Uri, System.Private.Uri","memoryReference":{"id":"9ba5ad9b-b88a-45de-8e08-aec043e22a10"}},"method":{"typeName":"String","memoryReference":{"id":"ab690185-cda3-44e6-8aaa-bb1c2a2e7941"}},"content":null,"contentType":null,"authorization":null,"requestHeaders":{"typeName":"Elsa.Http.Models.HttpRequestHeaders, Elsa.Http","expression":{"type":"Literal","value":"{}"},"memoryReference":{}},"parsedContent":null,"result":null,"id":"GetUsers1","name":null,"type":"Demo.Reqres.GetUsers","version":0,"customProperties":{"canStartWorkflow":false,"runAsynchronously":false},"metadata":{"designer":{"position":{"x":460,"y":260}}}}],"connections":[{"source":{"activity":"HttpEndpoint1","port":"Done"},"target":{"activity":"GetUsers1","port":"In"}},{"source":{"activity":"SetVariable1","port":"Done"},"target":{"activity":"WriteHttpResponse1","port":"In"}},{"source":{"activity":"GetUsers1","port":"Done"},"target":{"activity":"SetVariable1","port":"In"}}]}}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"id":"cfd60b01f85148b29e99b72d8c91754f","definitionId":"91390522c8674589bf9383e9c8e05447","name":"Get User","createdAt":"2023-07-13T14:10:52.554187+00:00","version":9,"variables":[{"id":"be5481f1f8f64df39012282404fbe7c7","name":"User","typeName":"Object","isArray":false,"value":"","storageDriverTypeName":"Elsa.Workflows.Core.Services.WorkflowStorageDriver, Elsa.Workflows.Core"},{"id":"abd12e6b760840e38e7e79e8430d33db","name":"UserId","typeName":"Int32","isArray":false,"value":"0","storageDriverTypeName":"Elsa.Workflows.Core.Services.WorkflowStorageDriver, Elsa.Workflows.Core"}],"inputs":[],"outputs":[],"outcomes":[],"customProperties":{},"isReadonly":false,"isLatest":true,"isPublished":true,"options":{"autoUpdateConsumingWorkflows":false},"root":{"type":"Elsa.Flowchart","version":1,"id":"Flowchart1","metadata":{},"customProperties":{"NotFoundConnectionsKey":[],"canStartWorkflow":false,"runAsynchronously":false},"start":"HttpEndpoint1","activities":[{"path":{"typeName":"String","expression":{"type":"Literal","value":"users/{userId}"},"memoryReference":{"id":"36cc8af8-3b83-49fd-aca2-1b8ba40583e8"}},"supportedMethods":{"typeName":"String[]","expression":{"type":"Object","value":"[\u0022GET\u0022]"},"memoryReference":{"id":"7389a64a-0fdb-4b8b-af55-72bad1eb72c9"}},"authorize":{"typeName":"Boolean","expression":{"type":"Literal","value":"False"},"memoryReference":{"id":"HttpEndpoint1:input-1"}},"policy":null,"parsedContent":null,"routeData":{"typeName":"ObjectDictionary","memoryReference":{"id":"ed6d5b4f6e794477837ee29e746e8ccb"}},"queryStringData":null,"headers":null,"result":null,"id":"HttpEndpoint1","name":null,"type":"Elsa.HttpEndpoint","version":1,"customProperties":{"canStartWorkflow":true,"runAsynchronously":false},"metadata":{"designer":{"position":{"x":260,"y":220}}}},{"variable":{"id":"abd12e6b760840e38e7e79e8430d33db","name":"UserId","typeName":"Int32","value":"0","storageDriverTypeName":"Elsa.Workflows.Core.Services.WorkflowStorageDriver, Elsa.Workflows.Core"},"value":{"typeName":"Object","expression":{"type":"JavaScript","value":"getRouteDataFromHttpEndpoint1()[\u0022userid\u0022]"},"memoryReference":{"id":"4ae05d95-e23f-4158-b53f-1043728d2ad1"}},"id":"SetVariable1","name":null,"type":"Elsa.SetVariable","version":1,"customProperties":{"canStartWorkflow":false,"runAsynchronously":false},"metadata":{"designer":{"position":{"x":520,"y":220}},"displayText":"Set UserId"}},{"expectedStatusCodes":[],"unmatchedStatusCode":null,"url":{"typeName":"System.Uri, System.Private.Uri","memoryReference":{"id":"31406d9b-528a-4149-aed6-4dacfd6d566a"}},"method":{"typeName":"String","memoryReference":{"id":"91cbdddc-1df1-42ed-b63a-8ed7cfae115a"}},"content":null,"contentType":null,"authorization":null,"requestHeaders":{"typeName":"Elsa.Http.Models.HttpRequestHeaders, Elsa.Http","expression":{"type":"Literal","value":"{}"},"memoryReference":{}},"parsedContent":{"typeName":"Object","memoryReference":{"id":"be5481f1f8f64df39012282404fbe7c7"}},"result":null,"id":"GetUser1","name":null,"type":"Demo.Reqres.GetUser","version":0,"customProperties":{"canStartWorkflow":false,"runAsynchronously":false},"metadata":{"designer":{"position":{"x":760,"y":220}}},"userId":{"typeName":"Int32","expression":{"type":"JavaScript","value":"getUserId()"},"memoryReference":{"id":"66cf67ac-5c36-48cd-8a3a-d24fb831e1b0"}}},{"statusCode":{"typeName":"System.Net.HttpStatusCode, System.Net.Primitives","expression":{"type":"Literal","value":"OK"},"memoryReference":{"id":"WriteHttpResponse1:input-1"}},"content":{"typeName":"Object","expression":{"type":"JavaScript","value":"getUser()"},"memoryReference":{"id":"36f78ecf-9b4c-4245-b1af-a44d9730b52e"}},"contentType":{"typeName":"String","expression":{"type":"Literal","value":"application/json"},"memoryReference":{"id":"5146a788-d413-4ea4-9ac7-99fcf717bb33"}},"responseHeaders":{"typeName":"Elsa.Http.Models.HttpResponseHeaders, Elsa.Http","expression":{"type":"Literal","value":"{}"},"memoryReference":{"id":"WriteHttpResponse1:input-2"}},"id":"WriteHttpResponse1","name":null,"type":"Elsa.WriteHttpResponse","version":1,"customProperties":{"canStartWorkflow":false,"runAsynchronously":false},"metadata":{"designer":{"position":{"x":940,"y":220}}}}],"connections":[{"source":{"activity":"HttpEndpoint1","port":"Done"},"target":{"activity":"SetVariable1","port":"In"}},{"source":{"activity":"SetVariable1","port":"Done"},"target":{"activity":"GetUser1","port":"In"}},{"source":{"activity":"GetUser1","port":"Done"},"target":{"activity":"WriteHttpResponse1","port":"In"}}]}}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
### Create a new user
|
||||
POST https://localhost:5001/workflows/users
|
||||
Content-Type: application/json
|
||||
Accept: application/json
|
||||
|
||||
{
|
||||
"name": "Bob",
|
||||
"job": "Postman"
|
||||
}
|
||||
|
||||
### Get all users
|
||||
GET https://localhost:5001/workflows/users/all
|
||||
Accept: application/json
|
||||
|
||||
### Get a user
|
||||
GET https://localhost:5001/workflows/users/2
|
||||
Accept: application/json
|
||||
Loading…
Reference in a new issue