如何让grpc像WCF一样抛出原始异常



我想知道是否有办法拥有Grpc。Net Core将服务器端的原始异常抛出给客户端。

问题如下。调用grpc服务时,例如:

客户:

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

服务器:

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

运行此操作时,会引发以下RpcException:

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

现在,我非常希望在客户端实际引发ArgumentException,以便更好地处理此问题。

我想,可能的是在我的Startup.cs中做以下事情:

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

结果:

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

这更好,但仍然不完美。

我的问题是-我能以某种方式在客户端引发服务器异常吗?我读到的是grpc允许";拦截器";以拦截grpc调用。这有可能在这里做点什么吗?

您可以设置一个Interceptor来捕获服务器端异常,序列化异常元数据,并将其打包到自定义RpcException中。客户端可以从RpcException反序列化元数据并重新创建异常。

下面是我发现的一篇博客文章,它贯穿了整个过程:ASP gRPC自定义错误处理

正如你所能想象的那样,不利的一面是,每一个例外都需要这样做。我也一直在研究同一个问题,但没有找到任何简单的方法将其应用于所有例外。

配置拦截器:

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

裸骨拦截器:

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;
}
}

最新更新