コード例 #1
0
        private IAsyncEnumerator <object> GetStreamingEnumerator(CloudHubConnectionContext connection,
                                                                 string invocationId, ObjectMethodExecutor methodExecutor, object result, Type resultType)
        {
            if (result != null)
            {
                var observableInterface = IsIObservable(resultType) ?
                                          resultType :
                                          resultType.GetInterfaces().FirstOrDefault(IsIObservable);
                if (observableInterface != null)
                {
                    return(AsyncEnumeratorAdapters.FromObservable(result, observableInterface, CreateCancellation()));
                }

                if (IsChannel(resultType, out var payloadType))
                {
                    return(AsyncEnumeratorAdapters.FromChannel(result, payloadType, CreateCancellation()));
                }
            }

            //Log.InvalidReturnValueFromStreamingMethod(_logger, methodExecutor.MethodInfo.Name);
            throw new InvalidOperationException($"The value returned by the streaming method '{methodExecutor.MethodInfo.Name}' is null, does not implement the IObservable<> interface or is not a ReadableChannel<>.");

            CancellationToken CreateCancellation()
            {
                var streamCts = new CancellationTokenSource();

                connection.ActiveRequestCancellationSources.TryAdd(invocationId, streamCts);
                return(CancellationTokenSource.CreateLinkedTokenSource(connection.ConnectionAbortedToken, streamCts.Token).Token);
            }
        }
コード例 #2
0
        private async Task Invoke(HubMethodDescriptor descriptor, CloudHubConnectionContext connection,
                                  HubMethodInvocationMessage hubMethodInvocationMessage, bool isStreamedInvocation)
        {
            var methodExecutor = descriptor.MethodExecutor;

            using (var scope = _serviceScopeFactory.CreateScope())
            {
                if (!await IsHubMethodAuthorized(scope.ServiceProvider, connection.User, descriptor.Policies))
                {
                    _logger.LogError($"Hub method unauthorized: {hubMethodInvocationMessage.Target}");
                    await SendInvocationError(hubMethodInvocationMessage, connection,
                                              $"Failed to invoke '{hubMethodInvocationMessage.Target}' because user is unauthorized");

                    return;
                }

                if (!await ValidateInvocationMode(methodExecutor.MethodReturnType, isStreamedInvocation, hubMethodInvocationMessage, connection))
                {
                    return;
                }

                var hubActivator = scope.ServiceProvider.GetRequiredService <IHubActivator <THub> >();
                var hub          = hubActivator.Create();

                try
                {
                    InitializeHub(hub, connection);

                    var result = await ExecuteHubMethod(methodExecutor, hub, hubMethodInvocationMessage.Arguments);

                    if (isStreamedInvocation)
                    {
                        var enumerator = GetStreamingEnumerator(connection, hubMethodInvocationMessage.InvocationId, methodExecutor, result, methodExecutor.MethodReturnType);
                        //Log.StreamingResult(_logger, hubMethodInvocationMessage.InvocationId, methodExecutor);
                        await StreamResultsAsync(hubMethodInvocationMessage.InvocationId, connection, enumerator);
                    }
                    // Non-empty/null InvocationId ==> Blocking invocation that needs a response
                    else if (!string.IsNullOrEmpty(hubMethodInvocationMessage.InvocationId))
                    {
                        //Log.SendingResult(_logger, hubMethodInvocationMessage.InvocationId, methodExecutor);
                        await connection.ReturnResultAsync(CompletionMessage.WithResult(hubMethodInvocationMessage.InvocationId, result));
                    }
                }
                catch (TargetInvocationException ex)
                {
                    //Log.FailedInvokingHubMethod(_logger, hubMethodInvocationMessage.Target, ex);
                    await SendInvocationError(hubMethodInvocationMessage, connection, ex.InnerException.Message);
                }
                catch (Exception ex)
                {
                    //Log.FailedInvokingHubMethod(_logger, hubMethodInvocationMessage.Target, ex);
                    await SendInvocationError(hubMethodInvocationMessage, connection, ex.Message);
                }
                finally
                {
                    hubActivator.Release(hub);
                }
            }
        }
コード例 #3
0
        private async Task StreamResultsAsync(string invocationId, CloudHubConnectionContext connection, IAsyncEnumerator <object> enumerator)
        {
            string error = null;

            try
            {
                while (await enumerator.MoveNextAsync())
                {
                    // Send the stream item
                    await connection.ReturnResultAsync(new StreamItemMessage(invocationId, enumerator.Current));
                }
            }
            catch (ChannelClosedException ex)
            {
                // If the channel closes from an exception in the streaming method, grab the innerException for the error from the streaming method
                error = ex.InnerException == null ? ex.Message : ex.InnerException.Message;
            }
            catch (Exception ex)
            {
                // If the streaming method was canceled we don't want to send a HubException message - this is not an error case
                if (!(ex is OperationCanceledException && connection.ActiveRequestCancellationSources.TryGetValue(invocationId, out var cts) &&
                      cts.IsCancellationRequested))
                {
                    error = ex.Message;
                }
            }
            finally
            {
                await connection.ReturnResultAsync(new CompletionMessage(invocationId, error : error, result : null, hasResult : false));

                if (connection.ActiveRequestCancellationSources.TryRemove(invocationId, out var cts))
                {
                    cts.Dispose();
                }
            }
        }
コード例 #4
0
 private async Task ProcessInvocation(CloudHubConnectionContext connection, HubMethodInvocationMessage hubMethodInvocationMessage, bool isStreamedInvocation)
 {
     try
     {
         // If an unexpected exception occurs then we want to kill the entire connection
         // by ending the processing loop
         if (!_methods.TryGetValue(hubMethodInvocationMessage.Target, out var descriptor))
         {
             // Send an error to the client. Then let the normal completion process occur
             _logger.LogWarning($"Unknown hub method: {hubMethodInvocationMessage.Target}");
             await SendInvocationError(hubMethodInvocationMessage, connection,
                                       $"Unknown hub method '{hubMethodInvocationMessage.Target}'");
         }
         else
         {
             await Invoke(descriptor, connection, hubMethodInvocationMessage, isStreamedInvocation);
         }
     }
     catch (Exception ex)
     {
         // Abort the entire connection if the invocation fails in an unexpected way
         connection.Abort(ex);
     }
 }