diff --git a/common.DotSettings b/common.DotSettings
index 5c1cda48fd..f2cc0339ae 100644
--- a/common.DotSettings
+++ b/common.DotSettings
@@ -38,5 +38,6 @@
False
False
False
+ True
True
\ No newline at end of file
diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln
index fadd40bcc5..4ce47bdbc8 100644
--- a/framework/Volo.Abp.sln
+++ b/framework/Volo.Abp.sln
@@ -409,6 +409,18 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.RemoteServices", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Mvc.PlugIn", "test\Volo.Abp.AspNetCore.Mvc.PlugIn\Volo.Abp.AspNetCore.Mvc.PlugIn.csproj", "{C6D6D878-208A-4FD2-822E-365545D8681B}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Dapr", "src\Volo.Abp.Dapr\Volo.Abp.Dapr.csproj", "{192A829F-D608-4E41-8DE0-058E943E453F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Dapr", "src\Volo.Abp.EventBus.Dapr\Volo.Abp.EventBus.Dapr.csproj", "{DCC41E99-EBC7-4F19-BA0D-A6F770D8E431}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Http.Client.Dapr", "src\Volo.Abp.Http.Client.Dapr\Volo.Abp.Http.Client.Dapr.csproj", "{18B796D2-D45D-41AE-9A42-75C9B14B20DF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Mvc.Dapr", "src\Volo.Abp.AspNetCore.Mvc.Dapr\Volo.Abp.AspNetCore.Mvc.Dapr.csproj", "{5EED625D-8D86-492A-BCB8-F6C8CD8D4AA1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Mvc.Dapr.EventBus", "src\Volo.Abp.AspNetCore.Mvc.Dapr.EventBus\Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.csproj", "{B02EF042-C39E-45C4-A92D-BF7554E1889D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.DistributedLocking.Dapr", "src\Volo.Abp.DistributedLocking.Dapr\Volo.Abp.DistributedLocking.Dapr.csproj", "{CAE48068-233C-47A9-BEAB-DDF521730E7A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1219,6 +1231,30 @@ Global
{C6D6D878-208A-4FD2-822E-365545D8681B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C6D6D878-208A-4FD2-822E-365545D8681B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C6D6D878-208A-4FD2-822E-365545D8681B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {192A829F-D608-4E41-8DE0-058E943E453F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {192A829F-D608-4E41-8DE0-058E943E453F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {192A829F-D608-4E41-8DE0-058E943E453F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {192A829F-D608-4E41-8DE0-058E943E453F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DCC41E99-EBC7-4F19-BA0D-A6F770D8E431}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DCC41E99-EBC7-4F19-BA0D-A6F770D8E431}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DCC41E99-EBC7-4F19-BA0D-A6F770D8E431}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DCC41E99-EBC7-4F19-BA0D-A6F770D8E431}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18B796D2-D45D-41AE-9A42-75C9B14B20DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18B796D2-D45D-41AE-9A42-75C9B14B20DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18B796D2-D45D-41AE-9A42-75C9B14B20DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18B796D2-D45D-41AE-9A42-75C9B14B20DF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5EED625D-8D86-492A-BCB8-F6C8CD8D4AA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5EED625D-8D86-492A-BCB8-F6C8CD8D4AA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5EED625D-8D86-492A-BCB8-F6C8CD8D4AA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5EED625D-8D86-492A-BCB8-F6C8CD8D4AA1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B02EF042-C39E-45C4-A92D-BF7554E1889D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B02EF042-C39E-45C4-A92D-BF7554E1889D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B02EF042-C39E-45C4-A92D-BF7554E1889D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B02EF042-C39E-45C4-A92D-BF7554E1889D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CAE48068-233C-47A9-BEAB-DDF521730E7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CAE48068-233C-47A9-BEAB-DDF521730E7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CAE48068-233C-47A9-BEAB-DDF521730E7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CAE48068-233C-47A9-BEAB-DDF521730E7A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1425,6 +1461,12 @@ Global
{3683340D-92F5-4B14-B77B-34A163333309} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{EDFFDA74-090D-439C-A58D-06CCF86D4423} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{C6D6D878-208A-4FD2-822E-365545D8681B} = {447C8A77-E5F0-4538-8687-7383196D04EA}
+ {192A829F-D608-4E41-8DE0-058E943E453F} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
+ {DCC41E99-EBC7-4F19-BA0D-A6F770D8E431} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
+ {18B796D2-D45D-41AE-9A42-75C9B14B20DF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
+ {5EED625D-8D86-492A-BCB8-F6C8CD8D4AA1} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
+ {B02EF042-C39E-45C4-A92D-BF7554E1889D} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
+ {CAE48068-233C-47A9-BEAB-DDF521730E7A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/FodyWeavers.xml b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/FodyWeavers.xml
new file mode 100644
index 0000000000..be0de3a908
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/FodyWeavers.xsd b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/FodyWeavers.xsd
new file mode 100644
index 0000000000..3f3946e282
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.csproj
new file mode 100644
index 0000000000..78b46cad27
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.csproj
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprEventBusModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprEventBusModule.cs
new file mode 100644
index 0000000000..333a5aae9a
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprEventBusModule.cs
@@ -0,0 +1,29 @@
+using Microsoft.AspNetCore.Http.Json;
+using Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.SystemTextJson;
+using Volo.Abp.EventBus.Dapr;
+using Volo.Abp.Json.SystemTextJson;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus;
+
+[DependsOn(
+ typeof(AbpAspNetCoreMvcDaprModule),
+ typeof(AbpEventBusDaprModule)
+)]
+public class AbpAspNetCoreMvcDaprEventBusModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ // TODO: Add NewtonsoftJson json converter.
+
+ Configure(options =>
+ {
+ options.SerializerOptions.Converters.Add(new AbpAspNetCoreMvcDaprSubscriptionDefinitionConverter());
+ });
+
+ Configure(options =>
+ {
+ options.JsonSerializerOptions.Converters.Add(new AbpAspNetCoreMvcDaprSubscriptionDefinitionConverter());
+ });
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprEventBusOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprEventBusOptions.cs
new file mode 100644
index 0000000000..02ca4c8e22
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprEventBusOptions.cs
@@ -0,0 +1,11 @@
+namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus;
+
+public class AbpAspNetCoreMvcDaprEventBusOptions
+{
+ public List Contributors { get; }
+
+ public AbpAspNetCoreMvcDaprEventBusOptions()
+ {
+ Contributors = new List();
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprPubSubConsts.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprPubSubConsts.cs
new file mode 100644
index 0000000000..e785f2e737
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprPubSubConsts.cs
@@ -0,0 +1,8 @@
+namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus;
+
+public class AbpAspNetCoreMvcDaprPubSubConsts
+{
+ public const string DaprSubscribeUrl = "dapr/subscribe";
+
+ public const string DaprEventCallbackUrl = "api/abp/dapr/event";
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprPubSubProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprPubSubProvider.cs
new file mode 100644
index 0000000000..e797bd2fc0
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprPubSubProvider.cs
@@ -0,0 +1,63 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Models;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.EventBus;
+using Volo.Abp.EventBus.Dapr;
+using Volo.Abp.EventBus.Distributed;
+
+namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus;
+
+public class AbpAspNetCoreMvcDaprPubSubProvider : ITransientDependency
+{
+ protected IServiceProvider ServiceProvider { get; }
+ protected AbpAspNetCoreMvcDaprEventBusOptions AspNetCoreMvcDaprEventBusOptions { get; }
+ protected AbpDaprEventBusOptions DaprEventBusOptions { get; }
+ protected AbpDistributedEventBusOptions DistributedEventBusOptions { get; }
+
+ public AbpAspNetCoreMvcDaprPubSubProvider(
+ IServiceProvider serviceProvider,
+ IOptions aspNetCoreDaprEventBusOptions,
+ IOptions daprEventBusOptions,
+ IOptions distributedEventBusOptions)
+ {
+ ServiceProvider = serviceProvider;
+ AspNetCoreMvcDaprEventBusOptions = aspNetCoreDaprEventBusOptions.Value;
+ DaprEventBusOptions = daprEventBusOptions.Value;
+ DistributedEventBusOptions = distributedEventBusOptions.Value;
+ }
+
+ public virtual async Task> GetSubscriptionsAsync()
+ {
+ var subscriptions = new List();
+ foreach (var handler in DistributedEventBusOptions.Handlers)
+ {
+ foreach (var @interface in handler.GetInterfaces().Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IDistributedEventHandler<>)))
+ {
+ var eventType = @interface.GetGenericArguments()[0];
+ var eventName = EventNameAttribute.GetNameOrDefault(eventType);
+
+ subscriptions.Add(new AbpAspNetCoreMvcDaprSubscriptionDefinition()
+ {
+ PubSubName = DaprEventBusOptions.PubSubName,
+ Topic = eventName,
+ Route = AbpAspNetCoreMvcDaprPubSubConsts.DaprEventCallbackUrl
+ });
+ }
+ }
+
+ if (AspNetCoreMvcDaprEventBusOptions.Contributors.Any())
+ {
+ using (var scope = ServiceProvider.CreateScope())
+ {
+ var context = new AbpAspNetCoreMvcDaprPubSubProviderContributorContext(scope.ServiceProvider, subscriptions);
+ foreach (var contributor in AspNetCoreMvcDaprEventBusOptions.Contributors)
+ {
+ await contributor.ContributeAsync(context);
+ }
+ }
+ }
+
+ return subscriptions;
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprPubSubProviderContributorContext.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprPubSubProviderContributorContext.cs
new file mode 100644
index 0000000000..564b541dec
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/AbpAspNetCoreMvcDaprPubSubProviderContributorContext.cs
@@ -0,0 +1,16 @@
+using Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Models;
+
+namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus;
+
+public class AbpAspNetCoreMvcDaprPubSubProviderContributorContext
+{
+ public IServiceProvider ServiceProvider { get; }
+
+ public List Subscriptions { get; }
+
+ public AbpAspNetCoreMvcDaprPubSubProviderContributorContext(IServiceProvider serviceProvider, List daprSubscriptionModels)
+ {
+ ServiceProvider = serviceProvider;
+ Subscriptions = daprSubscriptionModels;
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprPubSubController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprPubSubController.cs
new file mode 100644
index 0000000000..c97e793b53
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprPubSubController.cs
@@ -0,0 +1,36 @@
+using System.Text.Json;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Models;
+using Volo.Abp.Dapr;
+using Volo.Abp.EventBus.Dapr;
+
+namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Controllers;
+
+[Area("abp")]
+[RemoteService(Name = "abp")]
+public class AbpAspNetCoreMvcDaprPubSubController : AbpController
+{
+ [HttpGet(AbpAspNetCoreMvcDaprPubSubConsts.DaprSubscribeUrl)]
+ public virtual async Task> SubscribeAsync()
+ {
+ return await HttpContext.RequestServices.GetRequiredService().GetSubscriptionsAsync();
+ }
+
+ [HttpPost(AbpAspNetCoreMvcDaprPubSubConsts.DaprEventCallbackUrl)]
+ public virtual async Task EventsAsync()
+ {
+ var bodyJsonDocument = await JsonDocument.ParseAsync(HttpContext.Request.Body);
+ var request = JsonSerializer.Deserialize(bodyJsonDocument.RootElement.GetRawText(),
+ HttpContext.RequestServices.GetRequiredService>().Value.JsonSerializerOptions);
+
+ var distributedEventBus = HttpContext.RequestServices.GetRequiredService();
+ var daprSerializer = HttpContext.RequestServices.GetRequiredService();
+
+ var eventData = daprSerializer.Deserialize(bodyJsonDocument.RootElement.GetProperty("data").GetRawText(), distributedEventBus.GetEventType(request.Topic));
+ await distributedEventBus.TriggerHandlersAsync(distributedEventBus.GetEventType(request.Topic), eventData);
+
+ return Ok();
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/IAbpAspNetCoreMvcDaprPubSubProviderContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/IAbpAspNetCoreMvcDaprPubSubProviderContributor.cs
new file mode 100644
index 0000000000..87047cd7ec
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/IAbpAspNetCoreMvcDaprPubSubProviderContributor.cs
@@ -0,0 +1,6 @@
+namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus;
+
+public interface IAbpAspNetCoreMvcDaprPubSubProviderContributor
+{
+ Task ContributeAsync(AbpAspNetCoreMvcDaprPubSubProviderContributorContext context);
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Models/AbpAspNetCoreMvcDaprSubscriptionDefinition.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Models/AbpAspNetCoreMvcDaprSubscriptionDefinition.cs
new file mode 100644
index 0000000000..287e78e01a
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Models/AbpAspNetCoreMvcDaprSubscriptionDefinition.cs
@@ -0,0 +1,10 @@
+namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Models;
+
+public class AbpAspNetCoreMvcDaprSubscriptionDefinition
+{
+ public string PubSubName { get; set; }
+
+ public string Topic { get; set; }
+
+ public string Route { get; set; }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Models/AbpAspNetCoreMvcDaprSubscriptionRequest.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Models/AbpAspNetCoreMvcDaprSubscriptionRequest.cs
new file mode 100644
index 0000000000..46c04b5a44
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Models/AbpAspNetCoreMvcDaprSubscriptionRequest.cs
@@ -0,0 +1,8 @@
+namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Models;
+
+public class AbpAspNetCoreMvcDaprSubscriptionRequest
+{
+ public string PubSubName { get; set; }
+
+ public string Topic { get; set; }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/SystemTextJson/AbpAspNetCoreMvcDaprPubSubJsonNamingPolicy.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/SystemTextJson/AbpAspNetCoreMvcDaprPubSubJsonNamingPolicy.cs
new file mode 100644
index 0000000000..0aa6bd4f7c
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/SystemTextJson/AbpAspNetCoreMvcDaprPubSubJsonNamingPolicy.cs
@@ -0,0 +1,11 @@
+using System.Text.Json;
+
+namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.SystemTextJson;
+
+public class AbpAspNetCoreMvcDaprPubSubJsonNamingPolicy : JsonNamingPolicy
+{
+ public override string ConvertName(string name)
+ {
+ return name.ToLower();
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/SystemTextJson/AbpAspNetCoreMvcDaprSubscriptionDefinitionConverter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/SystemTextJson/AbpAspNetCoreMvcDaprSubscriptionDefinitionConverter.cs
new file mode 100644
index 0000000000..fa26d35ca6
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/SystemTextJson/AbpAspNetCoreMvcDaprSubscriptionDefinitionConverter.cs
@@ -0,0 +1,25 @@
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Models;
+
+namespace Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.SystemTextJson;
+
+public class AbpAspNetCoreMvcDaprSubscriptionDefinitionConverter : JsonConverter
+{
+ private JsonSerializerOptions _writeJsonSerializerOptions;
+
+ public override AbpAspNetCoreMvcDaprSubscriptionDefinition Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void Write(Utf8JsonWriter writer, AbpAspNetCoreMvcDaprSubscriptionDefinition value, JsonSerializerOptions options)
+ {
+ _writeJsonSerializerOptions ??= JsonSerializerOptionsHelper.Create(new JsonSerializerOptions(options)
+ {
+ PropertyNamingPolicy = new AbpAspNetCoreMvcDaprPubSubJsonNamingPolicy()
+ }, x => x == this);
+
+ JsonSerializer.Serialize(writer, value, _writeJsonSerializerOptions);
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/FodyWeavers.xml b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/FodyWeavers.xml
new file mode 100644
index 0000000000..be0de3a908
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/FodyWeavers.xsd b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/FodyWeavers.xsd
new file mode 100644
index 0000000000..3f3946e282
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo.Abp.AspNetCore.Mvc.Dapr.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo.Abp.AspNetCore.Mvc.Dapr.csproj
new file mode 100644
index 0000000000..d792a30b24
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo.Abp.AspNetCore.Mvc.Dapr.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/AbpAspNetCoreMvcDaprModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/AbpAspNetCoreMvcDaprModule.cs
new file mode 100644
index 0000000000..f8ba3fcfc2
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/AbpAspNetCoreMvcDaprModule.cs
@@ -0,0 +1,13 @@
+using Volo.Abp.Dapr;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.AspNetCore.Mvc.Dapr;
+
+[DependsOn(
+ typeof(AbpAspNetCoreMvcModule),
+ typeof(AbpDaprModule)
+)]
+public class AbpAspNetCoreMvcDaprModule : AbpModule
+{
+
+}
diff --git a/framework/src/Volo.Abp.Dapr/FodyWeavers.xml b/framework/src/Volo.Abp.Dapr/FodyWeavers.xml
new file mode 100644
index 0000000000..be0de3a908
--- /dev/null
+++ b/framework/src/Volo.Abp.Dapr/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Dapr/FodyWeavers.xsd b/framework/src/Volo.Abp.Dapr/FodyWeavers.xsd
new file mode 100644
index 0000000000..3f3946e282
--- /dev/null
+++ b/framework/src/Volo.Abp.Dapr/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Dapr/Volo.Abp.Dapr.csproj b/framework/src/Volo.Abp.Dapr/Volo.Abp.Dapr.csproj
new file mode 100644
index 0000000000..d3a8651086
--- /dev/null
+++ b/framework/src/Volo.Abp.Dapr/Volo.Abp.Dapr.csproj
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprClientFactory.cs b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprClientFactory.cs
new file mode 100644
index 0000000000..faaf450ddc
--- /dev/null
+++ b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprClientFactory.cs
@@ -0,0 +1,48 @@
+using System.Collections.Concurrent;
+using System.Text.Json;
+using Dapr.Client;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Json.SystemTextJson;
+
+namespace Volo.Abp.Dapr;
+
+public class AbpDaprClientFactory : ITransientDependency
+{
+ protected AbpDaprOptions Options { get; }
+ protected AbpSystemTextJsonSerializerOptions SystemTextJsonSerializerOptions { get; }
+
+ public AbpDaprClientFactory(
+ IOptions options,
+ IOptions systemTextJsonSerializerOptions)
+ {
+ Options = options.Value;
+ SystemTextJsonSerializerOptions = systemTextJsonSerializerOptions.Value;
+ }
+
+ public virtual async Task CreateAsync()
+ {
+ var builder = new DaprClientBuilder()
+ .UseJsonSerializationOptions(await CreateJsonSerializerOptions());
+
+ if (!Options.HttpEndpoint.IsNullOrWhiteSpace())
+ {
+ builder.UseHttpEndpoint(Options.HttpEndpoint);
+ }
+
+ if (!Options.GrpcEndpoint.IsNullOrWhiteSpace())
+ {
+ builder.UseGrpcEndpoint(Options.GrpcEndpoint);
+ }
+
+ return builder.Build();
+ }
+
+ private readonly static ConcurrentDictionary JsonSerializerOptionsCache = new ConcurrentDictionary();
+
+ protected virtual Task CreateJsonSerializerOptions()
+ {
+ return Task.FromResult(JsonSerializerOptionsCache.GetOrAdd(nameof(AbpDaprClientFactory),
+ _ => new JsonSerializerOptions(SystemTextJsonSerializerOptions.JsonSerializerOptions)));
+ }
+}
diff --git a/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprModule.cs b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprModule.cs
new file mode 100644
index 0000000000..43d6d11033
--- /dev/null
+++ b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprModule.cs
@@ -0,0 +1,15 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Json;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.Dapr;
+
+[DependsOn(typeof(AbpJsonModule))]
+public class AbpDaprModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ var configuration = context.Services.GetConfiguration();
+ Configure(configuration.GetSection("Dapr"));
+ }
+}
diff --git a/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprOptions.cs b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprOptions.cs
new file mode 100644
index 0000000000..9d743263c5
--- /dev/null
+++ b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprOptions.cs
@@ -0,0 +1,10 @@
+namespace Volo.Abp.Dapr;
+
+public class AbpDaprOptions
+{
+ public string AppId { get; set; }
+
+ public string HttpEndpoint { get; set; }
+
+ public string GrpcEndpoint { get; set; }
+}
diff --git a/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IDaprSerializer.cs b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IDaprSerializer.cs
new file mode 100644
index 0000000000..7eec2c5c1c
--- /dev/null
+++ b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IDaprSerializer.cs
@@ -0,0 +1,16 @@
+namespace Volo.Abp.Dapr;
+
+public interface IDaprSerializer
+{
+ byte[] Serialize(object obj);
+
+ object Deserialize(byte[] value, Type type);
+
+ T Deserialize(byte[] value);
+
+ string SerializeToString(object obj);
+
+ object Deserialize(string value, Type type);
+
+ T Deserialize(string value);
+}
diff --git a/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/Utf8JsonDaprSerializer.cs b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/Utf8JsonDaprSerializer.cs
new file mode 100644
index 0000000000..ce9b4a8523
--- /dev/null
+++ b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/Utf8JsonDaprSerializer.cs
@@ -0,0 +1,45 @@
+using System.Text;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Json;
+
+namespace Volo.Abp.Dapr;
+
+public class Utf8JsonDaprSerializer : IDaprSerializer, ITransientDependency
+{
+ private readonly IJsonSerializer _jsonSerializer;
+
+ public Utf8JsonDaprSerializer(IJsonSerializer jsonSerializer)
+ {
+ _jsonSerializer = jsonSerializer;
+ }
+
+ public byte[] Serialize(object obj)
+ {
+ return Encoding.UTF8.GetBytes(_jsonSerializer.Serialize(obj));
+ }
+
+ public object Deserialize(byte[] value, Type type)
+ {
+ return _jsonSerializer.Deserialize(type, Encoding.UTF8.GetString(value));
+ }
+
+ public T Deserialize(byte[] value)
+ {
+ return _jsonSerializer.Deserialize(Encoding.UTF8.GetString(value));
+ }
+
+ public string SerializeToString(object obj)
+ {
+ return _jsonSerializer.Serialize(obj);
+ }
+
+ public object Deserialize(string value, Type type)
+ {
+ return _jsonSerializer.Deserialize(type, value);
+ }
+
+ public T Deserialize(string value)
+ {
+ return _jsonSerializer.Deserialize(value);
+ }
+}
diff --git a/framework/src/Volo.Abp.DistributedLocking.Dapr/FodyWeavers.xml b/framework/src/Volo.Abp.DistributedLocking.Dapr/FodyWeavers.xml
new file mode 100644
index 0000000000..be0de3a908
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Dapr/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.DistributedLocking.Dapr/FodyWeavers.xsd b/framework/src/Volo.Abp.DistributedLocking.Dapr/FodyWeavers.xsd
new file mode 100644
index 0000000000..3f3946e282
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Dapr/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo.Abp.DistributedLocking.Dapr.csproj b/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo.Abp.DistributedLocking.Dapr.csproj
new file mode 100644
index 0000000000..80cad677a3
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo.Abp.DistributedLocking.Dapr.csproj
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/AbpDistributedLockDaprOptions.cs b/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/AbpDistributedLockDaprOptions.cs
new file mode 100644
index 0000000000..43feba3c3b
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/AbpDistributedLockDaprOptions.cs
@@ -0,0 +1,13 @@
+namespace Volo.Abp.DistributedLocking.Dapr;
+
+public class AbpDistributedLockDaprOptions
+{
+ public string StoreName { get; set; }
+
+ public TimeSpan DefaultTimeout { get; set; }
+
+ public AbpDistributedLockDaprOptions()
+ {
+ DefaultTimeout = TimeSpan.FromSeconds(30);
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/AbpDistributedLockingDaprModule.cs b/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/AbpDistributedLockingDaprModule.cs
new file mode 100644
index 0000000000..c915cfe2f7
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/AbpDistributedLockingDaprModule.cs
@@ -0,0 +1,11 @@
+using Volo.Abp.Dapr;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.DistributedLocking.Dapr;
+
+[DependsOn(
+ typeof(AbpDistributedLockingAbstractionsModule),
+ typeof(AbpDaprModule))]
+public class AbpDistributedLockingDaprModule : AbpModule
+{
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/DaprAbpDistributedLock.cs b/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/DaprAbpDistributedLock.cs
new file mode 100644
index 0000000000..7f95a56542
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/DaprAbpDistributedLock.cs
@@ -0,0 +1,50 @@
+using Microsoft.Extensions.Options;
+using Volo.Abp.Dapr;
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.DistributedLocking.Dapr;
+
+[Dependency(ReplaceServices = true)]
+public class DaprAbpDistributedLock : IAbpDistributedLock, ITransientDependency
+{
+ protected AbpDaprClientFactory DaprClientFactory { get; }
+ protected AbpDistributedLockDaprOptions DistributedLockDaprOptions { get; }
+ protected AbpDaprOptions DaprOptions { get; }
+
+ public DaprAbpDistributedLock(
+ AbpDaprClientFactory daprClientFactory,
+ IOptions distributedLockDaprOptions,
+ IOptions daprOptions)
+ {
+ DaprClientFactory = daprClientFactory;
+ DaprOptions = daprOptions.Value;
+ DistributedLockDaprOptions = distributedLockDaprOptions.Value;
+ }
+
+ public async Task TryAcquireAsync(
+ string name,
+ TimeSpan timeout = default,
+ CancellationToken cancellationToken = default)
+ {
+ if (timeout == default)
+ {
+ timeout = DistributedLockDaprOptions.DefaultTimeout;
+ }
+
+ var daprClient = await DaprClientFactory.CreateAsync();
+
+ var lockResponse = await daprClient.Lock(
+ DistributedLockDaprOptions.StoreName,
+ name,
+ DaprOptions.AppId,
+ (int)timeout.TotalSeconds,
+ cancellationToken);
+
+ if (lockResponse == null || !lockResponse.Success)
+ {
+ return null;
+ }
+
+ return new DaprAbpDistributedLockHandle(lockResponse);
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/DaprAbpDistributedLockHandle.cs b/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/DaprAbpDistributedLockHandle.cs
new file mode 100644
index 0000000000..b10f0f3672
--- /dev/null
+++ b/framework/src/Volo.Abp.DistributedLocking.Dapr/Volo/Abp/DistributedLocking/Dapr/DaprAbpDistributedLockHandle.cs
@@ -0,0 +1,18 @@
+using Dapr.Client;
+
+namespace Volo.Abp.DistributedLocking.Dapr;
+
+public class DaprAbpDistributedLockHandle : IAbpDistributedLockHandle
+{
+ protected TryLockResponse LockResponse { get; }
+
+ public DaprAbpDistributedLockHandle(TryLockResponse lockResponse)
+ {
+ LockResponse = lockResponse;
+ }
+
+ public async ValueTask DisposeAsync()
+ {
+ await LockResponse.DisposeAsync();
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/AbpDistributedLockingModule.cs b/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/AbpDistributedLockingModule.cs
index 4c4abd3f32..c642e33667 100644
--- a/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/AbpDistributedLockingModule.cs
+++ b/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/AbpDistributedLockingModule.cs
@@ -7,5 +7,4 @@ namespace Volo.Abp.DistributedLocking;
)]
public class AbpDistributedLockingModule : AbpModule
{
-
}
diff --git a/framework/src/Volo.Abp.EventBus.Dapr/FodyWeavers.xml b/framework/src/Volo.Abp.EventBus.Dapr/FodyWeavers.xml
new file mode 100644
index 0000000000..be0de3a908
--- /dev/null
+++ b/framework/src/Volo.Abp.EventBus.Dapr/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.EventBus.Dapr/FodyWeavers.xsd b/framework/src/Volo.Abp.EventBus.Dapr/FodyWeavers.xsd
new file mode 100644
index 0000000000..3f3946e282
--- /dev/null
+++ b/framework/src/Volo.Abp.EventBus.Dapr/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.EventBus.Dapr/Volo.Abp.EventBus.Dapr.csproj b/framework/src/Volo.Abp.EventBus.Dapr/Volo.Abp.EventBus.Dapr.csproj
new file mode 100644
index 0000000000..2bef3f9dc9
--- /dev/null
+++ b/framework/src/Volo.Abp.EventBus.Dapr/Volo.Abp.EventBus.Dapr.csproj
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/AbpDaprEventBusOptions.cs b/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/AbpDaprEventBusOptions.cs
new file mode 100644
index 0000000000..d3ced52ba2
--- /dev/null
+++ b/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/AbpDaprEventBusOptions.cs
@@ -0,0 +1,11 @@
+namespace Volo.Abp.EventBus.Dapr;
+
+public class AbpDaprEventBusOptions
+{
+ public string PubSubName { get; set; }
+
+ public AbpDaprEventBusOptions()
+ {
+ PubSubName = "pubsub";
+ }
+}
diff --git a/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/AbpEventBusDaprModule.cs b/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/AbpEventBusDaprModule.cs
new file mode 100644
index 0000000000..5f6329a4bc
--- /dev/null
+++ b/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/AbpEventBusDaprModule.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Dapr;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.EventBus.Dapr;
+
+[DependsOn(
+ typeof(AbpEventBusModule),
+ typeof(AbpDaprModule)
+ )]
+public class AbpEventBusDaprModule : AbpModule
+{
+ public override void OnApplicationInitialization(ApplicationInitializationContext context)
+ {
+ context
+ .ServiceProvider
+ .GetRequiredService()
+ .Initialize();
+ }
+}
diff --git a/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/DaprDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/DaprDistributedEventBus.cs
new file mode 100644
index 0000000000..1f241b9c6d
--- /dev/null
+++ b/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/DaprDistributedEventBus.cs
@@ -0,0 +1,221 @@
+using System.Collections.Concurrent;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Volo.Abp.Dapr;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.EventBus.Distributed;
+using Volo.Abp.Guids;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.Threading;
+using Volo.Abp.Timing;
+using Volo.Abp.Uow;
+
+namespace Volo.Abp.EventBus.Dapr;
+
+[Dependency(ReplaceServices = true)]
+[ExposeServices(typeof(IDistributedEventBus), typeof(DaprDistributedEventBus))]
+public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDependency
+{
+ protected IDaprSerializer Serializer { get; }
+ protected AbpDaprEventBusOptions DaprEventBusOptions { get; }
+ protected AbpDaprClientFactory DaprClientFactory { get; }
+
+ protected ConcurrentDictionary> HandlerFactories { get; }
+ protected ConcurrentDictionary EventTypes { get; }
+
+ public DaprDistributedEventBus(
+ IServiceScopeFactory serviceScopeFactory,
+ ICurrentTenant currentTenant,
+ IUnitOfWorkManager unitOfWorkManager,
+ IOptions abpDistributedEventBusOptions,
+ IGuidGenerator guidGenerator,
+ IClock clock,
+ IEventHandlerInvoker eventHandlerInvoker,
+ IDaprSerializer serializer,
+ IOptions daprEventBusOptions,
+ AbpDaprClientFactory daprClientFactory)
+ : base(serviceScopeFactory, currentTenant, unitOfWorkManager, abpDistributedEventBusOptions, guidGenerator, clock, eventHandlerInvoker)
+ {
+ Serializer = serializer;
+ DaprEventBusOptions = daprEventBusOptions.Value;
+ DaprClientFactory = daprClientFactory;
+
+ HandlerFactories = new ConcurrentDictionary>();
+ EventTypes = new ConcurrentDictionary();
+ }
+
+ public void Initialize()
+ {
+ SubscribeHandlers(AbpDistributedEventBusOptions.Handlers);
+ }
+
+ public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory)
+ {
+ var handlerFactories = GetOrCreateHandlerFactories(eventType);
+
+ if (factory.IsInFactories(handlerFactories))
+ {
+ return NullDisposable.Instance;
+ }
+
+ handlerFactories.Add(factory);
+
+ return new EventHandlerFactoryUnregistrar(this, eventType, factory);
+ }
+
+ public override void Unsubscribe(Func action)
+ {
+ Check.NotNull(action, nameof(action));
+
+ GetOrCreateHandlerFactories(typeof(TEvent))
+ .Locking(factories =>
+ {
+ factories.RemoveAll(
+ factory =>
+ {
+ var singleInstanceFactory = factory as SingleInstanceHandlerFactory;
+ if (singleInstanceFactory == null)
+ {
+ return false;
+ }
+
+ var actionHandler = singleInstanceFactory.HandlerInstance as ActionEventHandler;
+ if (actionHandler == null)
+ {
+ return false;
+ }
+
+ return actionHandler.Action == action;
+ });
+ });
+ }
+
+ public override void Unsubscribe(Type eventType, IEventHandler handler)
+ {
+ GetOrCreateHandlerFactories(eventType)
+ .Locking(factories =>
+ {
+ factories.RemoveAll(
+ factory =>
+ factory is SingleInstanceHandlerFactory &&
+ (factory as SingleInstanceHandlerFactory).HandlerInstance == handler
+ );
+ });
+ }
+
+ public override void Unsubscribe(Type eventType, IEventHandlerFactory factory)
+ {
+ GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Remove(factory));
+ }
+
+ public override void UnsubscribeAll(Type eventType)
+ {
+ GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Clear());
+ }
+
+ protected async override Task PublishToEventBusAsync(Type eventType, object eventData)
+ {
+ await PublishToDaprAsync(eventType, eventData);
+ }
+
+ protected override void AddToUnitOfWork(IUnitOfWork unitOfWork, UnitOfWorkEventRecord eventRecord)
+ {
+ unitOfWork.AddOrReplaceDistributedEvent(eventRecord);
+ }
+
+ protected override IEnumerable GetHandlerFactories(Type eventType)
+ {
+ var handlerFactoryList = new List();
+
+ foreach (var handlerFactory in HandlerFactories.Where(hf => ShouldTriggerEventForHandler(eventType, hf.Key)))
+ {
+ handlerFactoryList.Add(new EventTypeWithEventHandlerFactories(handlerFactory.Key, handlerFactory.Value));
+ }
+
+ return handlerFactoryList.ToArray();
+ }
+
+ public async override Task PublishFromOutboxAsync(OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig)
+ {
+ await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName)));
+ }
+
+ public async override Task PublishManyFromOutboxAsync(IEnumerable outgoingEvents, OutboxConfig outboxConfig)
+ {
+ var outgoingEventArray = outgoingEvents.ToArray();
+
+ foreach (var outgoingEvent in outgoingEventArray)
+ {
+ await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName)));
+ }
+ }
+
+ public async override Task ProcessFromInboxAsync(IncomingEventInfo incomingEvent, InboxConfig inboxConfig)
+ {
+ var eventType = EventTypes.GetOrDefault(incomingEvent.EventName);
+ if (eventType == null)
+ {
+ return;
+ }
+
+ var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType);
+ var exceptions = new List();
+ await TriggerHandlersAsync(eventType, eventData, exceptions, inboxConfig);
+ if (exceptions.Any())
+ {
+ ThrowOriginalExceptions(eventType, exceptions);
+ }
+ }
+
+ protected override byte[] Serialize(object eventData)
+ {
+ return Serializer.Serialize(eventData);
+ }
+
+ private List GetOrCreateHandlerFactories(Type eventType)
+ {
+ return HandlerFactories.GetOrAdd(
+ eventType,
+ type =>
+ {
+ var eventName = EventNameAttribute.GetNameOrDefault(type);
+ EventTypes[eventName] = type;
+ return new List();
+ }
+ );
+ }
+
+ public Type GetEventType(string eventName)
+ {
+ return EventTypes.GetOrDefault(eventName);
+ }
+
+ protected virtual async Task PublishToDaprAsync(Type eventType, object eventData)
+ {
+ await PublishToDaprAsync(EventNameAttribute.GetNameOrDefault(eventType), eventData);
+ }
+
+ protected virtual async Task PublishToDaprAsync(string eventName, object eventData)
+ {
+ var client = await DaprClientFactory.CreateAsync();
+ await client.PublishEventAsync(pubsubName: DaprEventBusOptions.PubSubName, topicName: eventName, data: eventData);
+ }
+
+ private static bool ShouldTriggerEventForHandler(Type targetEventType, Type handlerEventType)
+ {
+ //Should trigger same type
+ if (handlerEventType == targetEventType)
+ {
+ return true;
+ }
+
+ //TODO: Support inheritance? But it does not support on subscription to RabbitMq!
+ //Should trigger for inherited types
+ if (handlerEventType.IsAssignableFrom(targetEventType))
+ {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/framework/src/Volo.Abp.Http.Client.Dapr/FodyWeavers.xml b/framework/src/Volo.Abp.Http.Client.Dapr/FodyWeavers.xml
new file mode 100644
index 0000000000..be0de3a908
--- /dev/null
+++ b/framework/src/Volo.Abp.Http.Client.Dapr/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Http.Client.Dapr/FodyWeavers.xsd b/framework/src/Volo.Abp.Http.Client.Dapr/FodyWeavers.xsd
new file mode 100644
index 0000000000..3f3946e282
--- /dev/null
+++ b/framework/src/Volo.Abp.Http.Client.Dapr/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Http.Client.Dapr/Volo.Abp.Http.Client.Dapr.csproj b/framework/src/Volo.Abp.Http.Client.Dapr/Volo.Abp.Http.Client.Dapr.csproj
new file mode 100644
index 0000000000..909fb156c8
--- /dev/null
+++ b/framework/src/Volo.Abp.Http.Client.Dapr/Volo.Abp.Http.Client.Dapr.csproj
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/framework/src/Volo.Abp.Http.Client.Dapr/Volo/Abp/Http/Client/Dapr/AbpHttpClientDaprModule.cs b/framework/src/Volo.Abp.Http.Client.Dapr/Volo/Abp/Http/Client/Dapr/AbpHttpClientDaprModule.cs
new file mode 100644
index 0000000000..18a509d3ff
--- /dev/null
+++ b/framework/src/Volo.Abp.Http.Client.Dapr/Volo/Abp/Http/Client/Dapr/AbpHttpClientDaprModule.cs
@@ -0,0 +1,23 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Dapr;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.Http.Client.Dapr;
+
+[DependsOn(
+ typeof(AbpHttpClientModule),
+ typeof(AbpDaprModule)
+)]
+public class AbpHttpClientDaprModule : AbpModule
+{
+ public override void PreConfigureServices(ServiceConfigurationContext context)
+ {
+ PreConfigure(options =>
+ {
+ options.ProxyClientBuildActions.Add((_, clientBuilder) =>
+ {
+ clientBuilder.AddHttpMessageHandler();
+ });
+ });
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Http.Client.Dapr/Volo/Abp/Http/Client/Dapr/AbpInvocationHandler.cs b/framework/src/Volo.Abp.Http.Client.Dapr/Volo/Abp/Http/Client/Dapr/AbpInvocationHandler.cs
new file mode 100644
index 0000000000..a3397b55e4
--- /dev/null
+++ b/framework/src/Volo.Abp.Http.Client.Dapr/Volo/Abp/Http/Client/Dapr/AbpInvocationHandler.cs
@@ -0,0 +1,14 @@
+using Dapr.Client;
+using Microsoft.Extensions.Options;
+using Volo.Abp.Dapr;
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.Http.Client.Dapr;
+
+public class AbpInvocationHandler : InvocationHandler, ITransientDependency
+{
+ public AbpInvocationHandler(IOptions daprOptions)
+ {
+ DaprEndpoint = daprOptions.Value.HttpEndpoint;
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionHttpClientProxyExtensions.cs b/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionHttpClientProxyExtensions.cs
index 4ccac104cd..7bc239813d 100644
--- a/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionHttpClientProxyExtensions.cs
+++ b/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionHttpClientProxyExtensions.cs
@@ -212,7 +212,7 @@ public static class ServiceCollectionHttpClientProxyExtensions
}
///
- /// Checks wether the type is suitable to use with the proxying.
+ /// Checks whether the type is suitable to use with the proxying.
/// Currently the type is checked statically against some fixed conditions.
///
/// Type to check
diff --git a/nupkg/common.ps1 b/nupkg/common.ps1
index f13746aed0..6762cbce07 100644
--- a/nupkg/common.ps1
+++ b/nupkg/common.ps1
@@ -99,6 +99,8 @@ $projects = (
"framework/src/Volo.Abp.AspNetCore.Authentication.OAuth",
"framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect",
"framework/src/Volo.Abp.AspNetCore",
+ "framework/src/Volo.Abp.AspNetCore.Mvc.Dapr",
+ "framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus",
"framework/src/Volo.Abp.AspNetCore.Components",
"framework/src/Volo.Abp.AspNetCore.Components.Server",
"framework/src/Volo.Abp.AspNetCore.Components.Web",
@@ -155,12 +157,14 @@ $projects = (
"framework/src/Volo.Abp.Core",
"framework/src/Volo.Abp",
"framework/src/Volo.Abp.Dapper",
+ "framework/src/Volo.Abp.Dapr",
"framework/src/Volo.Abp.Data",
"framework/src/Volo.Abp.Ddd.Application",
"framework/src/Volo.Abp.Ddd.Application.Contracts",
"framework/src/Volo.Abp.Ddd.Domain",
"framework/src/Volo.Abp.DistributedLocking.Abstractions",
"framework/src/Volo.Abp.DistributedLocking",
+ "framework/src/Volo.Abp.DistributedLocking.Dapr",
"framework/src/Volo.Abp.Emailing",
"framework/src/Volo.Abp.EntityFrameworkCore",
"framework/src/Volo.Abp.EntityFrameworkCore.MySQL",
@@ -175,6 +179,7 @@ $projects = (
"framework/src/Volo.Abp.EventBus.Kafka",
"framework/src/Volo.Abp.EventBus.Rebus",
"framework/src/Volo.Abp.EventBus.Azure",
+ "framework/src/Volo.Abp.EventBus.Dapr",
"framework/src/Volo.Abp.ExceptionHandling",
"framework/src/Volo.Abp.Features",
"framework/src/Volo.Abp.FluentValidation",
@@ -184,7 +189,8 @@ $projects = (
"framework/src/Volo.Abp.HangFire",
"framework/src/Volo.Abp.Http.Abstractions",
"framework/src/Volo.Abp.Http.Client",
- "framework/src/Volo.Abp.Http.Client.Web",
+ "framework/src/Volo.Abp.Http.Client.Dapr",
+ "framework/src/Volo.Abp.Http.Client.Web",
"framework/src/Volo.Abp.Http.Client.IdentityModel",
"framework/src/Volo.Abp.Http.Client.IdentityModel.Web",
"framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly",