dotnet-sdk: Grpc.Core.RpcException when remote invocation results in BadRequest

Expected Behavior

The client sdk should be able to handle HTTP 400 Bad Request and make the request available to the calling application

Actual Behavior

When the app returns a HTTP400 or BadRequest object the dapr client fails with an exception.

Steps to Reproduce the Problem

Small modification of https://github.com/dapr/dotnet-sdk/blob/master/samples/AspNetCore/ControllerSample/Controllers/SampleController.cs to add the following method to return a BadRequest

/// Do
[HttpPost("do")]
public IActionResult Do(int value)
{
    Console.WriteLine($"Doing {value}"); 
    return BadRequest(new
    {
        value = value
    });
}

When calling the method on the client via

var a = await client.InvokeMethodAsync<object, Account>("routing", "do", data, httpExtension);

we are getting an exception

== APP == DepositUsingServiceInvocation

== APP == invoking

== APP == Unhandled exception. Grpc.Core.RpcException: Status(StatusCode=Internal, Detail="Bad Request")
== APP ==    at Dapr.Client.DaprClientGrpc.MakeGrpcCallHandleError[TResponse](Func`2 callFunc, CancellationToken cancellationToken) in /dotnet-sdk/src/Dapr.Client/DaprClientGrpc.cs:line 585

It seems there is no handling in the client sdk https://github.com/dapr/dotnet-sdk/blob/master/src/Dapr.Client/DaprClientGrpc.cs#L584

RELEASE NOTE: N/A

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 32 (32 by maintainers)

Most upvoted comments

moving back to dotnet-sdk. The fix for grpc-dotnet has been merged - https://github.com/grpc/grpc-dotnet/pull/1046 new version of grpc-dotnet will be released by this week or early next week. then we will use this version to fix this problem.

IMO we need to make sure we return the following information to the caller when invoking HTTP services, uniformly:

  1. Response text
  2. Status code
  3. Headers

@amanbha The Grpc.Core.RpcException class has a property trailers which can contain a list of metadata entries. A metadata entry can contain bytes which makes it able to transport the needed error details like response body and response headers. The HTTP status code can be transported in the status property of the RpcException.

The AsyncUnaryCall which is used by the DaprClientGrpc implementation does handle the trailers from the gRPC request.

Dapr explicitly ignores trailers for HTTP responses. Maybe here we can set also trailers with the required response data?

@akkie yes, I agree, thanks for pointing to the issue grpc-dotnet which needs to be fixed before users can examine it in the exception.