private async Task<InvocationResponse<TResponse>> MakeInvokeRequestAsyncWithResponse<TRequest, TResponse>( InvocationRequest<TRequest> request, bool useRaw, CancellationToken cancellationToken = default) { Any serializedData = null; if (request.Body != null) { if (useRaw) { // User has passed in raw bytes var requestBytes = (byte[])(object)(request.Body); serializedData = new Any { Value = ByteString.CopyFrom(requestBytes), TypeUrl = typeof(byte[]).FullName }; } else { serializedData = TypeConverters.ToAny(request.Body, this.jsonSerializerOptions); } } try { var invokeResponse = new InvocationResponse<TResponse>(); Autogenerated.InvokeServiceRequest invokeRequest; CallOptions callOptions; (invokeRequest, callOptions) = this.MakeInvokeRequestAsync(request.AppId, request.MethodName, serializedData, request.HttpExtension, cancellationToken); var grpcCall = client.InvokeServiceAsync(invokeRequest, callOptions); var response = await grpcCall.ResponseAsync; var responseHeaders = await grpcCall.ResponseHeadersAsync; var trailers = grpcCall.GetTrailers(); var grpcStatus = grpcCall.GetStatus(); var headers = grpcCall.ResponseHeadersAsync.Result.ToDictionary(kv => kv.Key, kv => kv.ValueBytes); if (useRaw) { // User wants to receive raw bytes var responseBytes = new byte[response.Data.Value.Length]; response.Data.Value?.CopyTo(responseBytes, 0); invokeResponse.Body = (TResponse)(response.Data.Value.IsEmpty ? default : (object)(responseBytes)); } else { invokeResponse.Body = response.Data.Value.IsEmpty ? default : TypeConverters.FromAny<TResponse>(response.Data, this.jsonSerializerOptions); } invokeResponse.Headers = headers; invokeResponse.Trailers = grpcCall.GetTrailers().ToDictionary(kv => kv.Key, kv => kv.ValueBytes); if (headers.TryGetValue(DaprHttpStatusHeader, out var httpStatus)) { invokeResponse.HttpStatusCode = (HttpStatusCode)System.Enum.Parse(typeof(HttpStatusCode), Encoding.UTF8.GetString(httpStatus, 0, httpStatus.Length)); invokeResponse.ContentType = Constants.ContentTypeApplicationJson; } else { // Response is grpc invokeResponse.GrpcStatusInfo = new GrpcStatusInfo(grpcStatus.StatusCode, grpcStatus.Detail); invokeResponse.ContentType = Constants.ContentTypeApplicationGrpc; } return invokeResponse; } catch (RpcException ex) { var invokeErrorResponse = new InvocationResponse<byte[]>(); var entry = ex.Trailers.Get(GrpcStatusDetails); if (entry != null) { var status = Google.Rpc.Status.Parser.ParseFrom(entry.ValueBytes); foreach (var detail in status.Details) { if (Google.Protobuf.WellKnownTypes.Any.GetTypeName(detail.TypeUrl) == GrpcErrorInfoDetail) { var rpcError = detail.Unpack<Google.Rpc.ErrorInfo>(); var grpcStatusCode = (StatusCode)status.Code; string innerHttpErrorCode = null; string innerHttpErrorMessage = null; rpcError.Metadata.TryGetValue(DaprErrorInfoHttpCodeMetadata, out innerHttpErrorCode); rpcError.Metadata.TryGetValue(DaprErrorInfoHttpErrorMetadata, out innerHttpErrorMessage); if(innerHttpErrorCode != null || innerHttpErrorMessage != null) { // Response returned by Http server invokeErrorResponse.HttpStatusCode = (HttpStatusCode)(Convert.ToInt32(innerHttpErrorCode)); invokeErrorResponse.Body = Encoding.UTF8.GetBytes(innerHttpErrorMessage); } else { // Response returned by gRPC server invokeErrorResponse.GrpcStatusInfo = new GrpcStatusInfo(grpcStatusCode, status.Message); } break; } } } throw new InvocationException($"Exception while invoking {request.MethodName} on appId:{request.AppId}", ex, invokeErrorResponse); } }