protected virtual async Task <TResponse> Execute <TResponse>(string method, object request, CallContext context) { AppHost.AssertFeatures(ServiceStack.Feature.Grpc); if (!Feature.DisableRequestParamsInHeaders) { PopulateRequestFromHeaders(request, context.CallOptions.Headers); } var req = new GrpcRequest(context, request, method); using var scope = req.StartScope(); var ret = await RpcGateway.ExecuteAsync <TResponse>(request, req); if (req.Response.Dto == null) { req.Response.Dto = ret; } await WriteResponseHeadersAsync(req.Response, context); return(ret); }
protected virtual async IAsyncEnumerable <TResponse> Stream <TRequest, TResponse>(TRequest request, CallContext context) { AppHost.AssertFeatures(ServiceStack.Feature.Grpc); if (!Feature.DisableRequestParamsInHeaders) { PopulateRequestFromHeaders(request, context.CallOptions.Headers); } if (!Feature.RequestServiceTypeMap.TryGetValue(typeof(TRequest), out var serviceType)) { throw new NotSupportedException($"'{typeof(TRequest).Name}' was not registered in GrpcFeature.RegisterServices"); } var service = (IStreamService <TRequest, TResponse>)AppHost.Container.Resolve(serviceType); using var disposableService = service as IDisposable; var req = new GrpcRequest(context, request, HttpMethods.Post); using var scope = req.StartScope(); var res = req.Response; if (service is IRequiresRequest requiresRequest) { requiresRequest.Request = req; } IAsyncEnumerable <TResponse> response = default; try { if (AppHost.ApplyPreRequestFilters(req, req.Response)) { yield break; } await AppHost.ApplyRequestFiltersAsync(req, res, request); if (res.IsClosed) { yield break; } response = service.Stream(request, context.CancellationToken); } catch (Exception e) { res.Dto = RpcGateway.CreateErrorResponse <TResponse>(res, e); await WriteResponseHeadersAsync(res, context); yield break; //written in headers } if (response != null) { var enumerator = response.GetAsyncEnumerator(); bool more; try { more = await enumerator.MoveNextAsync(); } catch (Exception e) { // catch + handle first Exception res.Dto = RpcGateway.CreateErrorResponse <TResponse>(res, e); await WriteResponseHeadersAsync(res, context); await enumerator.DisposeAsync(); yield break; //written in headers } yield return(enumerator.Current); while (more) { try { more = await enumerator.MoveNextAsync(); } catch (OperationCanceledException) { await enumerator.DisposeAsync(); yield break; } catch (Exception) { await enumerator.DisposeAsync(); yield break; } if (more) { yield return(enumerator.Current); } } await enumerator.DisposeAsync(); } }