Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get grpc to throw the original exception like WCF does?

Tags:

c#

.net-core

grpc

I was wondering whether there is a way to have Grpc .Net Core throw the original exception of the server side back to the client.

The problem is the following. When calling a grpc service, for example:

Client:

using (var channel = GrpcChannel.ForAddress("http://localhost:10042"))
{
    var greeterService = channel.CreateGrpcService<IGreetService>();
    var result = await greeterService.Greet();

    Console.WriteLine(result.Greet);
}

Server:

public async Task<Greeting> Greet()
{
    throw new ArgumentException();
}

Running this, the following RpcException is raised:

Grpc.Core.RpcException: 'Status(StatusCode=Unknown, Detail="Exception was thrown by handler.")'

Now, I would very much like to get this in a direction of actually raising an ArgumentException on the client side so this can be handled better.

What is possible, so I figured, is to do the following in my Startup.cs:

services.AddCodeFirstGrpc(options => options.EnableDetailedErrors = true); 

Result:

Grpc.Core.RpcException: 'Status(StatusCode=Unknown, Detail="Exception was thrown by handler. ArgumentException: Value does not fall within the expected range.")'

That's better, but still not perfect.

My question is - Can I somehow raise the servers exception on the client side? Something I read up on was the fact that grpc allows "Interceptors" to intercept grpc calls. Is this a possibility to maybe do something here?

like image 374
Sossenbinder Avatar asked Jul 09 '20 20:07

Sossenbinder


People also ask

Does gRPC replace WCF?

With WCF (Windows Communication Foundation) no longer being actively developed, gRPC (remote procedure call) appears to be the natural replacement when it comes to developing greenfield service applications on . NET Core and .

Does gRPC use http1?

grpc itself is a protocol that can be transported over basically anything, but http1.

What does gRPC use for better performance?

gRPC uses HTTP/2, which multiplexes multiple calls on a single TCP connection.


1 Answers

You can set up an Interceptor to catch server-side exceptions, serialize the exception metadata, and pack it into a custom RpcException. The client can deserialize the metadata from the RpcException and recreate the exception.

Here is a blog post I found that steps through the process: ASP gRPC Custom Error Handling

The downside, as you can imagine, is that this needs to be done for every exception. I've also been looking into the same question, and haven't found any straightforward ways to apply this to all exceptions.

Configure an interceptor:

services.AddGrpc(options => 
{
    options.Interceptors.Add<GRPCInterceptor>();     
});

Bare-bones interceptor:

public class GRPCInterceptor : Interceptor
{
    private readonly ILogger logger;

    public GRPCInterceptor(ILogger logger)
    {
        this.logger = logger;
    }

    public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)
    {
        logger.Debug($"starting call");

        var response = await base.UnaryServerHandler(request, context, continuation);

        logger.Debug($"finished call");

        return response;
    }
}
like image 142
Angela Yang Avatar answered Nov 12 '22 11:11

Angela Yang