diff --git a/Elsa.sln b/Elsa.sln
index b5572ce71..25818eded 100644
--- a/Elsa.sln
+++ b/Elsa.sln
@@ -245,11 +245,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Activities.Telnyx", "s
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Activities.Webhooks", "src\activities\Elsa.Activities.Webhooks\Elsa.Activities.Webhooks.csproj", "{2B67E954-3B04-402D-A9A7-AAAB1D6C3215}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Server.Orleans", "src\server\Elsa.Server.Orleans\Elsa.Server.Orleans.csproj", "{76BD888E-F0FD-40DD-B025-2ED773C1C50B}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Server.Orleans", "src\server\Elsa.Server.Orleans\Elsa.Server.Orleans.csproj", "{76BD888E-F0FD-40DD-B025-2ED773C1C50B}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Server.Hangfire", "src\server\Elsa.Server.Hangfire\Elsa.Server.Hangfire.csproj", "{546C123A-F855-459F-886C-9D90AA14D12B}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Server.Hangfire", "src\server\Elsa.Server.Hangfire\Elsa.Server.Hangfire.csproj", "{546C123A-F855-459F-886C-9D90AA14D12B}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.DocumentApproval", "src\samples\aspnet\Elsa.Samples.DocumentApproval\Elsa.Samples.DocumentApproval.csproj", "{C890480A-F21B-4F6F-821A-67FA19DAD539}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.DocumentApproval", "src\samples\aspnet\Elsa.Samples.DocumentApproval\Elsa.Samples.DocumentApproval.csproj", "{C890480A-F21B-4F6F-821A-67FA19DAD539}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Activities.BlobStorage", "src\activities\Elsa.Activities.BlobStorage\Elsa.Activities.BlobStorage.csproj", "{A80FC28D-D865-428D-AF12-7A393D407803}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -609,6 +611,10 @@ Global
{C890480A-F21B-4F6F-821A-67FA19DAD539}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C890480A-F21B-4F6F-821A-67FA19DAD539}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C890480A-F21B-4F6F-821A-67FA19DAD539}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A80FC28D-D865-428D-AF12-7A393D407803}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A80FC28D-D865-428D-AF12-7A393D407803}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A80FC28D-D865-428D-AF12-7A393D407803}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A80FC28D-D865-428D-AF12-7A393D407803}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -729,6 +735,7 @@ Global
{76BD888E-F0FD-40DD-B025-2ED773C1C50B} = {468E498C-59DB-4541-8D8A-0D89DE9083AB}
{546C123A-F855-459F-886C-9D90AA14D12B} = {468E498C-59DB-4541-8D8A-0D89DE9083AB}
{C890480A-F21B-4F6F-821A-67FA19DAD539} = {22E75696-6FE9-436A-9097-EE21C603F818}
+ {A80FC28D-D865-428D-AF12-7A393D407803} = {B43B546E-23F3-46E8-ACB7-D04F05CDA180}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8B0975FD-7050-48B0-88C5-48C33378E158}
diff --git a/src/activities/Elsa.Activities.BlobStorage/Activities/BlobExists.cs b/src/activities/Elsa.Activities.BlobStorage/Activities/BlobExists.cs
new file mode 100644
index 000000000..b8cbba8f1
--- /dev/null
+++ b/src/activities/Elsa.Activities.BlobStorage/Activities/BlobExists.cs
@@ -0,0 +1,43 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Elsa.ActivityResults;
+using Elsa.Attributes;
+using Elsa.Services;
+using Elsa.Services.Models;
+using Storage.Net.Blobs;
+
+// ReSharper disable once CheckNamespace
+namespace Elsa.Activities.BlobStorage
+{
+ ///
+ /// Writes a text string to the console.
+ ///
+ [Action(
+ Category = "BlobStorage",
+ Outcomes = new[] { OutcomeNames.True, OutcomeNames.False }
+ )]
+ public class BlobExists : Activity
+ {
+ public BlobExists(IBlobStorage storage)
+ {
+ _storage = storage;
+ }
+ private readonly IBlobStorage _storage;
+
+ [ActivityProperty(Hint = "The ID of the blob")]
+ public string BlobID { get; set; }
+
+ protected override async ValueTask OnExecuteAsync(ActivityExecutionContext context)
+ {
+ if (string.IsNullOrWhiteSpace(BlobID))
+ throw new System.Exception($"BlobID must have a value");
+ if (await _storage.ExistsAsync(BlobID))
+ return Outcome(OutcomeNames.True);
+ else
+ return Outcome(OutcomeNames.False);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/activities/Elsa.Activities.BlobStorage/Activities/DeleteBlob.cs b/src/activities/Elsa.Activities.BlobStorage/Activities/DeleteBlob.cs
new file mode 100644
index 000000000..b1abd83f6
--- /dev/null
+++ b/src/activities/Elsa.Activities.BlobStorage/Activities/DeleteBlob.cs
@@ -0,0 +1,45 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Elsa.ActivityResults;
+using Elsa.Attributes;
+using Elsa.Services;
+using Elsa.Services.Models;
+using Storage.Net.Blobs;
+
+// ReSharper disable once CheckNamespace
+namespace Elsa.Activities.BlobStorage
+{
+ ///
+ /// Writes a text string to the console.
+ ///
+ [Action(
+ Category = "BlobStorage",
+ Outcomes = new[] { OutcomeNames.Done }
+ )]
+ public class DeleteBlob : Activity
+ {
+ public DeleteBlob(IBlobStorage storage)
+ {
+ _storage = storage;
+ }
+ private readonly IBlobStorage _storage;
+
+ [ActivityProperty(Hint = "The ID of the blob")]
+ public string BlobID { get; set; }
+ [ActivityProperty(Hint = "The IDs of the blob")]
+ public List BlobIDs { get; set; } = new List();
+
+ protected override async ValueTask OnExecuteAsync(ActivityExecutionContext context)
+ {
+ if (string.IsNullOrWhiteSpace(BlobID) && (BlobIDs==default || !BlobIDs.Any()))
+ throw new System.Exception($"BlobID or BlobIds must have a value");
+ if (BlobID != default)
+ BlobIDs.Add(BlobID);
+ await _storage.DeleteAsync(BlobIDs);
+ return Done();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/activities/Elsa.Activities.BlobStorage/Activities/ReadBlob.cs b/src/activities/Elsa.Activities.BlobStorage/Activities/ReadBlob.cs
new file mode 100644
index 000000000..035326db5
--- /dev/null
+++ b/src/activities/Elsa.Activities.BlobStorage/Activities/ReadBlob.cs
@@ -0,0 +1,49 @@
+using System.ComponentModel.DataAnnotations;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Elsa.ActivityResults;
+using Elsa.Attributes;
+using Elsa.Services;
+using Elsa.Services.Models;
+using Storage.Net.Blobs;
+
+// ReSharper disable once CheckNamespace
+namespace Elsa.Activities.BlobStorage
+{
+ ///
+ /// Writes a text string to the console.
+ ///
+ [Action(
+ Category = "BlobStorage",
+ Description = "Reads a blob from the storage engine",
+ Outcomes = new[] { OutcomeNames.Done }
+ )]
+ public class ReadBlob : Activity
+ {
+ public ReadBlob(IBlobStorage storage)
+ {
+ _storage = storage;
+ }
+ private readonly IBlobStorage _storage;
+
+ [ActivityProperty(Hint = "The ID to be assigned to the blob. It's needed to retrieve the blob")]
+ [Required]
+ public string BlobID { get; set; }
+ [ActivityProperty(Hint = "The bytes")]
+ public byte[] Bytes { get; set; }
+ [ActivityProperty(Hint = "The output file path, alternative to Bytes")]
+ public string FilePath { get; set; }
+
+ protected override async ValueTask OnExecuteAsync(ActivityExecutionContext context)
+ {
+ if (string.IsNullOrWhiteSpace(BlobID))
+ throw new System.Exception($"BlobID must have a value");
+ if (!string.IsNullOrWhiteSpace(FilePath))
+ await _storage.ReadToFileAsync(BlobID, FilePath, context.CancellationToken);
+ else
+ Bytes = await _storage.ReadBytesAsync(BlobID);
+ return Done();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/activities/Elsa.Activities.BlobStorage/Activities/WriteBlob.cs b/src/activities/Elsa.Activities.BlobStorage/Activities/WriteBlob.cs
new file mode 100644
index 000000000..21736ec87
--- /dev/null
+++ b/src/activities/Elsa.Activities.BlobStorage/Activities/WriteBlob.cs
@@ -0,0 +1,49 @@
+using System.ComponentModel.DataAnnotations;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Elsa.ActivityResults;
+using Elsa.Attributes;
+using Elsa.Services;
+using Elsa.Services.Models;
+using Storage.Net.Blobs;
+
+// ReSharper disable once CheckNamespace
+namespace Elsa.Activities.BlobStorage
+{
+ ///
+ /// Writes a text string to the console.
+ ///
+ [Action(
+ Category = "BlobStorage",
+ Description = "Write a blob to the storage engine",
+ Outcomes = new[] { OutcomeNames.Done }
+ )]
+ public class WriteBlob : Activity
+ {
+ public WriteBlob(IBlobStorage storage)
+ {
+ _storage = storage;
+ }
+ private readonly IBlobStorage _storage;
+
+ [ActivityProperty(Hint = "The ID to be assigned to the blob. It's needed to retrieve the blob")]
+ [Required]
+ public string BlobID { get; set; }
+ [ActivityProperty(Hint = "The bytes")]
+ public byte[] Bytes { get; set; }
+ [ActivityProperty(Hint = "The file path")]
+ public string FilePath { get; set; }
+
+ protected override async ValueTask OnExecuteAsync(ActivityExecutionContext context)
+ {
+ if (string.IsNullOrWhiteSpace(BlobID))
+ throw new System.Exception($"BlobID must have a value");
+ if (!string.IsNullOrWhiteSpace(FilePath))
+ await _storage.WriteFileAsync(BlobID, FilePath, context.CancellationToken);
+ if(Bytes!=default && Bytes.Any())
+ await _storage.WriteAsync(BlobID, new MemoryStream(Bytes), default, context.CancellationToken);
+ return Done();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/activities/Elsa.Activities.BlobStorage/Elsa.Activities.BlobStorage.csproj b/src/activities/Elsa.Activities.BlobStorage/Elsa.Activities.BlobStorage.csproj
new file mode 100644
index 000000000..102c2fca5
--- /dev/null
+++ b/src/activities/Elsa.Activities.BlobStorage/Elsa.Activities.BlobStorage.csproj
@@ -0,0 +1,16 @@
+
+
+
+ netstandard2.1
+ Luca Pisano
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/activities/Elsa.Activities.BlobStorage/Extensions/ServiceCollectionExtensions.cs b/src/activities/Elsa.Activities.BlobStorage/Extensions/ServiceCollectionExtensions.cs
new file mode 100644
index 000000000..34a83eb37
--- /dev/null
+++ b/src/activities/Elsa.Activities.BlobStorage/Extensions/ServiceCollectionExtensions.cs
@@ -0,0 +1,27 @@
+using System;
+using System.IO;
+using System.Linq;
+using Elsa;
+using Elsa.Activities.BlobStorage;
+using Storage.Net.Blobs;
+
+// ReSharper disable once CheckNamespace
+namespace Microsoft.Extensions.DependencyInjection
+{
+ public static class ServiceCollectionExtensions
+ {
+ public static ElsaOptions AddBlobStorageActivities(this ElsaOptions options, Func implementation=default)
+ {
+ if (implementation != default)
+ options.UseStorage(implementation);
+ options
+ .AddActivity()
+ .AddActivity()
+ .AddActivity()
+ .AddActivity()
+ ;
+
+ return options;
+ }
+ }
+}
\ No newline at end of file