private async Task Invoke(HubMethodDescriptor descriptor, HubConnectionContext connection, HubMethodInvocationMessage hubMethodInvocationMessage, bool isStreamedInvocation) { var methodExecutor = descriptor.MethodExecutor; using (var scope = _serviceScopeFactory.CreateScope()) { if (!await IsHubMethodAuthorized(scope.ServiceProvider, connection.User, descriptor.Policies)) { _logger.HubMethodNotAuthorized(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); _logger.StreamingResult(hubMethodInvocationMessage.InvocationId, methodExecutor.MethodReturnType.FullName); await StreamResultsAsync(hubMethodInvocationMessage.InvocationId, connection, enumerator); } // Non-empty/null InvocationId ==> Blocking invocation that needs a response else if (!string.IsNullOrEmpty(hubMethodInvocationMessage.InvocationId)) { _logger.SendingResult(hubMethodInvocationMessage.InvocationId, methodExecutor.MethodReturnType.FullName); await SendMessageAsync(connection, CompletionMessage.WithResult(hubMethodInvocationMessage.InvocationId, result)); } } catch (TargetInvocationException ex) { _logger.FailedInvokingHubMethod(hubMethodInvocationMessage.Target, ex); await SendInvocationError(hubMethodInvocationMessage, connection, ex.InnerException.Message); } catch (Exception ex) { _logger.FailedInvokingHubMethod(hubMethodInvocationMessage.Target, ex); await SendInvocationError(hubMethodInvocationMessage, connection, ex.Message); } finally { hubActivator.Release(hub); } } }
private void DiscoverHubMethods() { var hubType = typeof(THub); var hubTypeInfo = hubType.GetTypeInfo(); foreach (var methodInfo in HubReflectionHelper.GetHubMethods(hubType)) { var methodName = methodInfo.Name; if (_methods.ContainsKey(methodName)) { throw new NotSupportedException($"Duplicate definitions of '{methodName}'. Overloading is not supported."); } var executor = ObjectMethodExecutor.Create(methodInfo, hubTypeInfo); var authorizeAttributes = methodInfo.GetCustomAttributes <AuthorizeAttribute>(inherit: true); _methods[methodName] = new HubMethodDescriptor(executor, authorizeAttributes); _logger.HubMethodBound(methodName); } }
private async Task Invoke(HubMethodDescriptor descriptor, HubConnectionContext connection, InvocationMessage invocationMessage) { var methodExecutor = descriptor.MethodExecutor; using (var scope = _serviceScopeFactory.CreateScope()) { if (!await IsHubMethodAuthorized(scope.ServiceProvider, connection.User, descriptor.Policies)) { _logger.HubMethodNotAuthorized(invocationMessage.Target); if (!invocationMessage.NonBlocking) { await SendMessageAsync(connection, CompletionMessage.WithError(invocationMessage.InvocationId, $"Failed to invoke '{invocationMessage.Target}' because user is unauthorized")); } return; } var hubActivator = scope.ServiceProvider.GetRequiredService <IHubActivator <THub> >(); var hub = hubActivator.Create(); try { InitializeHub(hub, connection); object result = null; // ReadableChannel is awaitable but we don't want to await it. if (methodExecutor.IsMethodAsync && !IsChannel(methodExecutor.MethodReturnType, out _)) { if (methodExecutor.MethodReturnType == typeof(Task)) { await(Task) methodExecutor.Execute(hub, invocationMessage.Arguments); } else { result = await methodExecutor.ExecuteAsync(hub, invocationMessage.Arguments); } } else { result = methodExecutor.Execute(hub, invocationMessage.Arguments); } if (IsStreamed(connection, invocationMessage.InvocationId, methodExecutor, result, methodExecutor.MethodReturnType, out var enumerator)) { _logger.StreamingResult(invocationMessage.InvocationId, methodExecutor.MethodReturnType.FullName); await StreamResultsAsync(invocationMessage.InvocationId, connection, enumerator); } else if (!invocationMessage.NonBlocking) { _logger.SendingResult(invocationMessage.InvocationId, methodExecutor.MethodReturnType.FullName); await SendMessageAsync(connection, CompletionMessage.WithResult(invocationMessage.InvocationId, result)); } } catch (TargetInvocationException ex) { _logger.FailedInvokingHubMethod(invocationMessage.Target, ex); await SendInvocationError(invocationMessage, connection, methodExecutor.MethodReturnType, ex.InnerException); } catch (Exception ex) { _logger.FailedInvokingHubMethod(invocationMessage.Target, ex); await SendInvocationError(invocationMessage, connection, methodExecutor.MethodReturnType, ex); } finally { hubActivator.Release(hub); } } }