question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

InvokeMethodAsync API is too permissive for DAPR 0.7

See original GitHub issue

I just upgraded my small DAPR playground project from 0.6 to 0.7. After that, my remote invocation calls stopped working with the following exception:

Grpc.Core.RpcException: Status(StatusCode=InvalidArgument, Detail="missing HTTP extension field")
   at Dapr.Client.DaprClientGrpc.MakeGrpcCallHandleError[TResponse](Func`2 callFunc, CancellationToken cancellationToken)
   at Dapr.Client.DaprClientGrpc.MakeInvokeRequestAsync(String appId, String methodName, Any data, HTTPExtension httpExtension, CancellationToken cancellationToken)
   at Dapr.Client.DaprClientGrpc.InvokeMethodAsync[TRequest,TResponse](String appId, String methodName, TRequest data, HTTPExtension httpExtension, CancellationToken cancellationToken)
   at DotNetBa.Dapr.Main.Controllers.UserController.Login(LoginModel model, DaprClient dapr, CancellationToken cancellationToken) in C:\Source\Personal\dotnetba-dapr\src\DotNetBa.Dapr.Main\Controllers\UserController.cs:line 44
   at lambda_method(Closure , Object )
   at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

I traced this to the following DAPR source: https://github.com/dapr/dapr/blob/41df721108185a399cf6c9096fe414bacb1d8b5d/pkg/channel/http/http_channel.go#L68

This looks like the remote invocation now requires the HTTPExtension to be specified. However, the call to InvokeMethodAsync marks that parameter as optional with default value of null (all overloads): https://github.com/dapr/dotnet-sdk/blob/44ca6496d8c29e14df2122f6704d24b38a1755a4/src/Dapr.Client/DaprClient.cs#L59-L63

This allows the user to write valid code that cannot work at runtime. I think the API surface should be made stricter to prevent this user error:

// original code - worked in 0.6 and broke in 0.7 (compiles in both)
await dapr.InvokeMethodAsync<LoginRequest, LoginResponse>(Apps.UserService,
                                                                          "login/login",
                                                                          request,
                                                                          cancellationToken: cancellationToken);

// new code - works in 0.7
await dapr.InvokeMethodAsync<LoginRequest, LoginResponse>(Apps.UserService,
                                                                          "login/login",
                                                                          request,
                                                                          new HTTPExtension() { Verb = HTTPVerb.Post },
                                                                          cancellationToken: cancellationToken)

This constitutes a breaking change that has not been documented (or maybe I just wasn’t able to find it). Therefore I’d like to propose a slight change to the API that would make the HTTPExtension parameter required.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:10 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
youngbuparkcommented, May 6, 2020

I have updated release note and create the pr to add additional comment.

1reaction
youngbuparkcommented, May 6, 2020

I will add this breaking change to release note as well.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How-To: Invoke services using HTTP | Dapr Docs
To invoke an application using Dapr, you can use the invoke API on any Dapr instance. The sidecar programming model encourages each application...
Read more >
The Dapr service invocation building block
Any application can invoke a Dapr sidecar by using the native invoke API built into Dapr. The API can be called with either...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found