// register connection with requested RPC managers private async Task UpgradeAsync(IConnection connection) { foreach (var manager in _managers.Values) { if (await Authorizations.AuthorizeControllerAsync(_authorization, manager.SubType, connection.Context.User)) { manager.Upgrade(connection); } } var readyMessage = new JObject(); var controllers = from manager in _managers.Values select manager.Name; readyMessage.Add("Controllers", JToken.FromObject(controllers)); var routes = from manager in _managers.Values from action in manager.Actions select new { Controller = manager.Name, Action = action.Key }; readyMessage.Add("Routes", JToken.FromObject(routes)); await connection.Send(readyMessage); }
// route a remote call to the appropriate action private async Task HandleMessageAsync(IConnection connection) { // get next message var message = await connection.Receive(); // extract controller name and action name from message var controllerName = message.Value <string>("Controller"); var actionName = message.Value <string>("Action"); if (controllerName == null || actionName == null) { _logger.LogWarning("RPC call failed because of malformed message"); return; } // get specified controller type IRPCManager manager; if (!_managers.TryGetValue(controllerName, out manager)) { _logger.LogWarning($"RPC call [{controllerName}] failed because no such manager existed "); return; } // get specified action method info MethodInfo actionMethod; if (!manager.Actions.TryGetValue(actionName, out actionMethod)) { _logger.LogWarning($"RPC call [{controllerName}.{actionName}] failed because no such action existed "); return; } // check authorization bool authorized = await Authorizations.AuthorizeControllerAsync(_authorization, manager.SubType, connection.Context.User); if (!authorized) { _logger.LogWarning($"RPC call [{controllerName}.{actionName}] failed because user wasn't authorized"); return; } authorized = await Authorizations.AuthorizeActionAsync(_authorization, actionMethod, connection.Context.User); if (!authorized) { _logger.LogWarning($"RPC call [{controllerName}.{actionName}] failed because user wasn't authorized"); return; } // extract the method parameters object[] parameters; if (!TryExtractParameters(message, actionMethod, out parameters)) { _logger.LogWarning($"RPC call [{controllerName}.{actionName}] failed because invalid parameters were sent"); return; } // create a new controller instance var descriptor = new ControllerActionDescriptor(); descriptor.ControllerTypeInfo = manager.SubType.GetTypeInfo(); descriptor.RouteValues["controller"] = controllerName; descriptor.RouteValues["action"] = actionName; var actionContext = new ActionContext(connection.Context, new RouteData(), descriptor); var controllerContext = new ControllerContext(actionContext); var controller = _factory.CreateController(controllerContext); if (controller == null) { _logger.LogWarning($"RPC call failed, because {controllerName} Controller could not be created"); return; } // call the action try { actionMethod.Invoke(controller, parameters); } catch (Exception ex) { _logger.LogError($"RPC Connection failed call to {controllerName}.{actionName}, because of exception: {ex.Message}"); return; } finally { _factory.ReleaseController(controllerContext, controller); } }