diff --git a/Elsa.sln b/Elsa.sln
index 851dc810a..44b64a5df 100644
--- a/Elsa.sln
+++ b/Elsa.sln
@@ -174,6 +174,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.HangfireIntegr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.ProtoActorRuntime", "src\samples\aspnet\Elsa.Samples.ProtoActorRuntime\Elsa.Samples.ProtoActorRuntime.csproj", "{A41E24C6-B16D-4C6A-A9A9-2C5AF424F20F}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.WorkflowContexts", "src\samples\aspnet\Elsa.Samples.WorkflowContexts\Elsa.Samples.WorkflowContexts.csproj", "{F88AB1C2-100E-459F-B2BE-5F2ACF050A0A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -432,6 +434,10 @@ Global
{A41E24C6-B16D-4C6A-A9A9-2C5AF424F20F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A41E24C6-B16D-4C6A-A9A9-2C5AF424F20F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A41E24C6-B16D-4C6A-A9A9-2C5AF424F20F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F88AB1C2-100E-459F-B2BE-5F2ACF050A0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F88AB1C2-100E-459F-B2BE-5F2ACF050A0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F88AB1C2-100E-459F-B2BE-5F2ACF050A0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F88AB1C2-100E-459F-B2BE-5F2ACF050A0A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{155227F0-A33B-40AA-A4B4-06F813EB921B} = {61017E64-6D00-49CB-9E81-5002DC8F7D5F}
@@ -508,5 +514,6 @@ Global
{B0312D9E-FA30-43E9-B666-40A8782D6E1C} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5}
{D2614FC7-102F-4F78-BB06-7C87304A10BA} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5}
{A41E24C6-B16D-4C6A-A9A9-2C5AF424F20F} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5}
+ {F88AB1C2-100E-459F-B2BE-5F2ACF050A0A} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5}
EndGlobalSection
EndGlobal
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Contracts/ICustomerStore.cs b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Contracts/ICustomerStore.cs
new file mode 100644
index 000000000..f957146eb
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Contracts/ICustomerStore.cs
@@ -0,0 +1,10 @@
+namespace Elsa.Samples.WorkflowContexts.Contracts;
+
+///
+/// A sample repository of customers.
+///
+public interface ICustomerStore
+{
+ Task GetAsync(string id, CancellationToken cancellationToken = default);
+ Task SaveAsync(Customer customer, CancellationToken cancellationToken = default);
+}
\ No newline at end of file
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Dockerfile b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Dockerfile
new file mode 100644
index 000000000..0d58c3066
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Dockerfile
@@ -0,0 +1,20 @@
+FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
+WORKDIR /app
+EXPOSE 80
+EXPOSE 443
+
+FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
+WORKDIR /src
+COPY ["src/samples/aspnet/Elsa.Samples.WorkflowContexts/Elsa.Samples.WorkflowContexts.csproj", "src/samples/aspnet/Elsa.Samples.WorkflowContexts/"]
+RUN dotnet restore "src/samples/aspnet/Elsa.Samples.WorkflowContexts/Elsa.Samples.WorkflowContexts.csproj"
+COPY . .
+WORKDIR "/src/src/samples/aspnet/Elsa.Samples.WorkflowContexts"
+RUN dotnet build "Elsa.Samples.WorkflowContexts.csproj" -c Release -o /app/build
+
+FROM build AS publish
+RUN dotnet publish "Elsa.Samples.WorkflowContexts.csproj" -c Release -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "Elsa.Samples.WorkflowContexts.dll"]
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Elsa.Samples.WorkflowContexts.csproj b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Elsa.Samples.WorkflowContexts.csproj
new file mode 100644
index 000000000..aaf4dbf46
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Elsa.Samples.WorkflowContexts.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net7.0
+ enable
+ enable
+ Linux
+
+
+
+
+ .dockerignore
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Entities/Customer.cs b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Entities/Customer.cs
new file mode 100644
index 000000000..97cbbc3f2
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Entities/Customer.cs
@@ -0,0 +1,10 @@
+namespace Elsa.Samples.WorkflowContexts.Contracts;
+
+public class Customer
+{
+ public string Id { get; set; }
+ public string Name { get; set; }
+ public string Email { get; set; }
+ public string Phone { get; set; }
+ public string Website { get; set; }
+}
\ No newline at end of file
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Extensions/ExpressionExecutionContextExtensions.cs b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Extensions/ExpressionExecutionContextExtensions.cs
new file mode 100644
index 000000000..69e96e64b
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Extensions/ExpressionExecutionContextExtensions.cs
@@ -0,0 +1,11 @@
+using Elsa.Expressions.Models;
+using Elsa.Extensions;
+using Elsa.Samples.WorkflowContexts.Contracts;
+using Elsa.Samples.WorkflowContexts.Providers;
+
+namespace Elsa.Samples.WorkflowContexts.Extensions;
+
+public static class ExpressionExecutionContextExtensions
+{
+ public static Customer GetCustomer(this ExpressionExecutionContext context) => context.GetWorkflowContext();
+}
\ No newline at end of file
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Extensions/WorkflowExecutionContextExtensions.cs b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Extensions/WorkflowExecutionContextExtensions.cs
new file mode 100644
index 000000000..c879625d7
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Extensions/WorkflowExecutionContextExtensions.cs
@@ -0,0 +1,10 @@
+using Elsa.Workflows.Core.Models;
+
+namespace Elsa.Samples.WorkflowContexts.Extensions;
+
+public static class WorkflowExecutionContextExtensions
+{
+ private const string CustomerIdKey = "CustomerId";
+ public static string? GetCustomerId(this WorkflowExecutionContext context) => context.GetProperty(CustomerIdKey);
+ public static void SetCustomerId(this WorkflowExecutionContext context, string? customerId) => context.SetProperty(CustomerIdKey, customerId);
+}
\ No newline at end of file
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Program.cs b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Program.cs
new file mode 100644
index 000000000..f31418c4b
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Program.cs
@@ -0,0 +1,106 @@
+using Elsa.EntityFrameworkCore.Extensions;
+using Elsa.EntityFrameworkCore.Modules.Management;
+using Elsa.EntityFrameworkCore.Modules.Runtime;
+using Elsa.Extensions;
+using Elsa.Samples.WorkflowContexts.Contracts;
+using Elsa.Samples.WorkflowContexts.Providers;
+using Elsa.Samples.WorkflowContexts.Services;
+using Elsa.Samples.WorkflowContexts.Workflows;
+using Elsa.Workflows.Core.Middleware.Workflows;
+
+var builder = WebApplication.CreateBuilder(args);
+var services = builder.Services;
+var configuration = builder.Configuration;
+var sqliteConnectionString = configuration.GetConnectionString("Sqlite")!;
+var identitySection = configuration.GetSection("Identity");
+var identityTokenSection = identitySection.GetSection("Tokens");
+
+// Add Elsa services.
+services
+ .AddElsa(elsa => elsa
+ .AddActivitiesFrom()
+ .AddWorkflow()
+ .UseIdentity(identity =>
+ {
+ identity.IdentityOptions = options => identitySection.Bind(options);
+ identity.TokenOptions = options => identityTokenSection.Bind(options);
+ identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options));
+ identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options));
+ identity.UseConfigurationBasedRoleProvider(options => identitySection.Bind(options));
+ })
+ .UseDefaultAuthentication()
+ .UseWorkflows(workflows => workflows.WithWorkflowExecutionPipeline(pipeline => pipeline
+ .Reset()
+ .UsePersistentVariables()
+ .UseBookmarkPersistence()
+ .UseWorkflowExecutionLogPersistence()
+ .UseWorkflowStatePersistence()
+ .UseWorkflowContexts()
+ .UseDefaultActivityScheduler()
+ ))
+ .UseWorkflowManagement(management =>
+ {
+ // Use EF core for workflow definitions and instances.
+ management.UseWorkflowInstances(m => m.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString)));
+ management.UseEntityFrameworkCore(m => m.UseSqlite(sqliteConnectionString));
+ })
+ .UseWorkflowRuntime(runtime =>
+ {
+ // Use EF core for triggers and bookmarks.
+ runtime.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString));
+
+ // Use EF core for execution log records.
+ runtime.UseExecutionLogRecords(log => log.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString)));
+
+ // Use the default workflow runtime with EF core.
+ runtime.UseDefaultRuntime(defaultRuntime => defaultRuntime.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString)));
+
+ // Install a workflow state exporter to capture workflow states and store them in IWorkflowInstanceStore.
+ runtime.UseAsyncWorkflowStateExporter();
+ })
+ .UseScheduling()
+ .UseWorkflowsApi(api => api.AddFastEndpointsAssembly())
+ .UseJavaScript()
+ .UseLiquid()
+ .UseHttp()
+ .UseEmail(email => email.ConfigureOptions = options => configuration.GetSection("Smtp").Bind(options))
+ );
+
+// Add health checks.
+services.AddHealthChecks();
+
+// Add CORS.
+services.AddCors(cors => cors.AddDefaultPolicy(policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()));
+
+// Add domain services.
+services.AddSingleton();
+
+// Add workflow context providers.
+services.AddWorkflowContextProvider();
+
+// Configure middleware pipeline.
+var app = builder.Build();
+
+if (app.Environment.IsDevelopment())
+ app.UseDeveloperExceptionPage();
+
+// CORS.
+app.UseCors();
+
+// Health checks.
+app.MapHealthChecks("/");
+
+app.UseAuthentication();
+app.UseAuthorization();
+
+// Elsa API endpoints for designer.
+app.UseWorkflowsApi();
+
+// Captures unhandled exceptions and returns a JSON response.
+app.UseJsonSerializationErrorHandler();
+
+// Elsa HTTP Endpoint activities
+app.UseWorkflows();
+
+// Run.
+app.Run();
\ No newline at end of file
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Properties/launchSettings.json b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Properties/launchSettings.json
new file mode 100644
index 000000000..a937a615b
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Properties/launchSettings.json
@@ -0,0 +1,37 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:32709",
+ "sslPort": 44321
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:5286",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:7019;http://localhost:5286",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Providers/CustomerWorkflowContextProvider.cs b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Providers/CustomerWorkflowContextProvider.cs
new file mode 100644
index 000000000..02b6698dc
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Providers/CustomerWorkflowContextProvider.cs
@@ -0,0 +1,31 @@
+using Elsa.Samples.WorkflowContexts.Contracts;
+using Elsa.Samples.WorkflowContexts.Extensions;
+using Elsa.WorkflowContexts.Abstractions;
+using Elsa.Workflows.Core.Models;
+
+namespace Elsa.Samples.WorkflowContexts.Providers;
+
+public class CustomerWorkflowContextProvider : WorkflowContextProvider
+{
+ private readonly ICustomerStore _customerStore;
+
+ public CustomerWorkflowContextProvider(ICustomerStore customerStore)
+ {
+ _customerStore = customerStore;
+ }
+
+ protected override async ValueTask LoadAsync(WorkflowExecutionContext workflowExecutionContext)
+ {
+ var customerId = workflowExecutionContext.GetCustomerId();
+ return customerId != null ? await _customerStore.GetAsync(customerId) : null;
+ }
+
+ protected override async ValueTask SaveAsync(WorkflowExecutionContext workflowExecutionContext, Customer? context)
+ {
+ if (context != null)
+ {
+ await _customerStore.SaveAsync(context);
+ workflowExecutionContext.SetCustomerId(context.Id);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/README.md b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/README.md
new file mode 100644
index 000000000..1a514869e
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/README.md
@@ -0,0 +1,10 @@
+# Server
+
+This project represents an Elsa application that hosts workflows and exposes API endpoints to manage & execute workflows.
+
+## Secrets
+The following are the secrets stored in hashed form in appsettings.json:
+
+**API key**: `4E753976726458745954355043687772-e54d5a2c-33a3-4c05-a216-b09569062aed`
+**Admin user**: `admin`
+**Admin password**: `password`
\ No newline at end of file
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Services/MemoryCustomerStore.cs b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Services/MemoryCustomerStore.cs
new file mode 100644
index 000000000..0eb4cb79d
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Services/MemoryCustomerStore.cs
@@ -0,0 +1,53 @@
+using Elsa.Samples.WorkflowContexts.Contracts;
+
+namespace Elsa.Samples.WorkflowContexts.Services;
+
+///
+/// An in-memory implementation of .
+///
+public class MemoryCustomerStore : ICustomerStore
+{
+ private readonly IDictionary _customers = CreateCustomersDatabase();
+
+ public Task GetAsync(string id, CancellationToken cancellationToken = default)
+ {
+ return Task.FromResult(_customers.TryGetValue(id, out var customer) ? customer : null);
+ }
+
+ public Task SaveAsync(Customer customer, CancellationToken cancellationToken = default)
+ {
+ _customers[customer.Id] = customer;
+ return Task.CompletedTask;
+ }
+
+ private static IDictionary CreateCustomersDatabase()
+ {
+ return new Dictionary
+ {
+ ["1"] = new()
+ {
+ Id = "1",
+ Name = "John Doe",
+ Email = "john.doe@acme.com",
+ Phone = "+1 555 123 4567",
+ Website = "https://acme.com"
+ },
+ ["2"] = new()
+ {
+ Id = "2",
+ Name = "Alice Smith",
+ Email = "alice.smith@example.com",
+ Phone = "+1 555 123 4567",
+ Website = "https://example.com"
+ },
+ ["3"] = new()
+ {
+ Id = "3",
+ Name = "Bob Jones",
+ Email = "bob.jones@supplier.com",
+ Phone = "+1 555 123 4567",
+ Website = "https://supplier.com"
+ },
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Workflows/CustomerCommunicationsWorkflow.cs b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Workflows/CustomerCommunicationsWorkflow.cs
new file mode 100644
index 000000000..182bd5859
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/Workflows/CustomerCommunicationsWorkflow.cs
@@ -0,0 +1,57 @@
+using Elsa.Email.Activities;
+using Elsa.Extensions;
+using Elsa.Samples.WorkflowContexts.Extensions;
+using Elsa.Samples.WorkflowContexts.Providers;
+using Elsa.Scheduling.Activities;
+using Elsa.Workflows.Core.Abstractions;
+using Elsa.Workflows.Core.Activities;
+using Elsa.Workflows.Core.Contracts;
+
+namespace Elsa.Samples.WorkflowContexts.Workflows;
+
+///
+/// A workflow that sends annoying emails to customers.
+///
+public class CustomerCommunicationsWorkflow : WorkflowBase
+{
+ protected override void Build(IWorkflowBuilder builder)
+ {
+ builder.AddWorkflowContextProvider();
+
+ builder.Root = new Sequence
+ {
+ Activities =
+ {
+ Inline.From(context => context.WorkflowExecutionContext.SetCustomerId(context.GetInput("CustomerId"))),
+ Delay.FromSeconds(5),
+ new SendEmail
+ {
+ Subject = new(context => $"Welcome to our family, {context.GetCustomer().Name}!"),
+ Body = new("Welcome aboard!"),
+ To = new(context => new[] { context.GetCustomer().Email })
+ },
+ Delay.FromSeconds(5),
+ new SendEmail
+ {
+ Subject = new(context => $"{context.GetCustomer().Name}, we got great deals for you!"),
+ Body = new("Get your creditcard ready!"),
+ To = new(context => new[] { context.GetCustomer().Email })
+ },
+ Delay.FromSeconds(5),
+ new SendEmail
+ {
+ Subject = new(context => $"{context.GetCustomer().Name}, you're missing out!"),
+ Body = new("Sale ends in 2 hours!"),
+ To = new(context => new[] { context.GetCustomer().Email })
+ },
+ Delay.FromSeconds(5),
+ new SendEmail
+ {
+ Subject = new(context => $"{context.GetCustomer().Name}, the clock is ticking!"),
+ Body = new("Tick tik tick!"),
+ To = new(context => new[] { context.GetCustomer().Email })
+ },
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/appsettings.json b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/appsettings.json
new file mode 100644
index 000000000..b8d078878
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/appsettings.json
@@ -0,0 +1,57 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Debug",
+ "Elsa.Mediator": "Warning",
+ "MassTransit": "Warning",
+ "Microsoft.Extensions.Http": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information",
+ "Microsoft.EntityFrameworkCore": "Warning",
+ "Microsoft.AspNetCore": "Warning",
+ "System.Net.Http": "Warning"
+ }
+ },
+ "AllowedHosts": "*",
+ "ConnectionStrings": {
+ "Sqlite": "Data Source=elsa.sqlite.db;Cache=Shared;"
+ },
+ "Identity": {
+ "Tokens": {
+ "SigningKey": "secret-signing-key",
+ "AccessTokenLifetime": "1:00:00:00",
+ "RefreshTokenLifetime": "1:00:10:00"
+ },
+ "Roles": [{
+ "Id": "admin",
+ "Name": "Administrator",
+ "Permissions": ["*"]
+ }],
+ "Users": [
+ {
+ "Id": "a2323f46-42db-4e15-af8b-94238717d817",
+ "Name": "admin",
+ "HashedPassword": "TfKzh9RLix6FPcCNeHLkGrysFu3bYxqzGqduNdi8v1U=",
+ "HashedPasswordSalt": "JEy9kBlhHCNsencitRHlGxmErmSgY+FVyMJulCH27Ds=",
+ "Roles": ["admin"]
+ }
+ ],
+ "Applications": [{
+ "id": "529572c2df854b13807b8bf23f1784cd",
+ "name": "Postman",
+ "roles": [
+ "admin"
+ ],
+ "clientId": "Nu9vrdXtYT5PChwr",
+ "clientSecret": "011pp2C$|j01-qrMZpC9VC0F00XCJq(5",
+ "hashedApiKey": "d0rDld3A+ugKmdctGtMzOLTYjQFkOlUWN+kt0VyW9D0=",
+ "hashedApiKeySalt": "EnutGOyy5MuJWV0fF5jCQiciK7a8PU/DRF+fr6nekSY=",
+ "hashedClientSecret": "ERia2zBcCSWb/9dvB0grQ9yf7fWgFrClNeR8A5RMTzk=",
+ "hashedClientSecretSalt": "z3z8KmzHt+xkAj/zYTXcB8I7y0xAkLm95v4Er/oNqiY="
+ }]
+ },
+ "Smtp": {
+ "Host": "localhost",
+ "Port": 2525,
+ "DefaultSender": "noreply@crmservices.com"
+ }
+}
diff --git a/src/samples/aspnet/Elsa.Samples.WorkflowContexts/docker-compose.yaml b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/docker-compose.yaml
new file mode 100644
index 000000000..452ce9877
--- /dev/null
+++ b/src/samples/aspnet/Elsa.Samples.WorkflowContexts/docker-compose.yaml
@@ -0,0 +1,12 @@
+version: '3.9'
+
+services:
+
+ smtp4dev:
+ image: rnwood/smtp4dev:3.1.3-ci20211206101
+ ports:
+ - "3000:80"
+ - "2525:25"
+
+volumes:
+ mssql-azuresql-edge-data:
\ No newline at end of file