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);
}
Run Code Online (Sandbox Code Playgroud)
Server:
public async Task<Greeting> Greet()
{
throw new ArgumentException();
}
Run Code Online (Sandbox Code Playgroud)
Running this, the following RpcException is raised:
Grpc.Core.RpcException: 'Status(StatusCode=Unknown, Detail="Exception was thrown by handler.")'
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
Result:
Grpc.Core.RpcException: 'Status(StatusCode=Unknown, Detail="Exception was thrown by handler. ArgumentException: Value does not fall within the expected range.")'
Run Code Online (Sandbox Code Playgroud)
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?
您可以设置拦截器来捕获服务器端异常,序列化异常元数据,并将其打包到自定义的RpcException. 客户端可以反序列化元数据RpcException并重新创建异常。
这是我发现的一篇博客文章,详细介绍了该过程:ASP gRPC Custom Error Handling
正如您可以想象的那样,缺点是需要对每个异常执行此操作。我也一直在研究同样的问题,但没有找到任何直接的方法来将其应用于所有异常。
配置拦截器:
services.AddGrpc(options =>
{
options.Interceptors.Add<GRPCInterceptor>();
});
Run Code Online (Sandbox Code Playgroud)
简单的拦截器:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
998 次 |
| 最近记录: |