abpframework / abp

Open-source web application framework for ASP.NET Core! Offers an opinionated architecture to build enterprise software solutions with best practices on top of the .NET. Provides the fundamental infrastructure, cross-cutting-concern implementations, startup templates, application modules, UI themes, tooling and documentation.
https://abp.io
GNU Lesser General Public License v3.0
12.82k stars 3.42k forks source link

[AbpAspNetCoreMvcDaprEventBusModule] Issues encountered in ABP Integration with Dapr DistributedEventBus #18239

Closed Euynac closed 10 months ago

Euynac commented 10 months ago

Is there an existing issue for this?

Description

I appreciate the integration of Dapr within the framework; however, I've encountered challenges that need attention.

Documentation lack of clarity

While meticulously following the documentation for my project setup, specifically regarding endpoints such as /dapr/subscribe, I faced difficulty achieving the expected results. Upon extensive investigation, I discovered that the addition of app.UseConfiguredEndpoints(); is necessary for ABP to appropriately register the relevant endpoints.

Subscriber Error

Upon configuring the endpoints as directed, I managed to acquire two endpoints for Dapr invocation. Nevertheless, an error persists:

2023-11-23 17:32:13 System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
2023-11-23 17:32:13    at System.Text.Json.JsonElement.GetProperty(String propertyName)
2023-11-23 17:32:13    at Volo.Abp.AspNetCore.Mvc.Dapr.EventBus.Controllers.AbpAspNetCoreMvcDaprEventsController.EventAsync()
2023-11-23 17:32:13    at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
2023-11-23 17:32:13    at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
2023-11-23 17:32:13    at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
2023-11-23 17:32:13    at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
2023-11-23 17:32:13    at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
2023-11-23 17:32:13    at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
2023-11-23 17:32:13 --- End of stack trace from previous location ---
2023-11-23 17:32:13    at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

The error stems from the source code of AbpAspNetCoreMvcDaprEventsController, specifically:

     var pubSubName = body.RootElement.GetProperty("pubsubname").GetString();
     var topic = body.RootElement.GetProperty("topic").GetString();
     var data = body.RootElement.GetProperty("data").GetRawText();
     if (pubSubName.IsNullOrWhiteSpace() || topic.IsNullOrWhiteSpace() || data.IsNullOrWhiteSpace())
     {
         Logger.LogError("Invalid Dapr event request.");
         return BadRequest();
     }

The problem lies in the exception thrown when a JSON property isn't found, leading to the failure of the conditional check. If there is no json property named given key, it will throw exception rather than given null or empty, so the judge part will never work if there has some error in request body.

Source Code Adjustment

I identified that the root cause of the unsupported request JSON format is the hardcoded metadata: rawPayload: true in AbpAspNetCoreMvcDaprEventBusModule. Despite attempting to disable app.UseCloudEvents(), the issue persisted.

       var subscription = new AbpSubscription
       {
           PubsubName = daprEventBusOptions.PubSubName,
           Topic = eventName,
           Route = AbpAspNetCoreMvcDaprPubSubConsts.DaprEventCallbackUrl,
           //I commented on it and worked.
           //Metadata = new AbpMetadata
           //{
           //    {
           //        AbpMetadata.RawPayload, "true"
           //    }
           //}
       };

Upon experimentation, I discovered that altering rawPayload to false enables proper functionality between ABP pubsub and Dapr.

For reference, here's a link detailing the specifications of Dapr pubsub regarding raw payload: dapr pubsub about raw payload

I would greatly appreciate any guidance or assistance in rectifying these issues to ensure seamless interoperability between ABP and Dapr's DistributedEventBus.

Reproduction Steps

No response

Expected behavior

No response

Actual behavior

No response

Regression?

No response

Known Workarounds

No response

Version

7.4.2

User Interface

Common (Default)

Database Provider

EF Core (Default)

Tiered or separate authentication server

None (Default)

Operation System

Windows (Default)

Other information

No response

maliming commented 10 months ago

hi

Please check the Dapr integration sample.

https://github.com/abpframework/abp-samples/tree/master/Dapr

Euynac commented 10 months ago

Thank you for the information. I discovered that in order to parse the Content-Type application/cloudevents+json with JSON format data_base64 while setting RawPayload to true, I have to use the app.UseCloudEvents() middleware. Additionally, this middleware should be placed before the app.UseConfiguredEndpoints() middleware to work.