public HubInvokerContext(IHub hub, StateChangeTracker tracker, MethodDescriptor methodDescriptor, IList<object> args) { Hub = hub; MethodDescriptor = methodDescriptor; Args = args; StateTracker = tracker; }
/// <summary> /// Searches the specified <paramref name="hub">Hub</paramref> for the specified <paramref name="method"/>. /// </summary> /// <remarks> /// In the case that there are multiple overloads of the specified <paramref name="method"/>, the <paramref name="parameters">parameter set</paramref> helps determine exactly which instance of the overload should be resolved. /// If there are multiple overloads found with the same number of matching parameters, none of the methods will be returned because it is not possible to determine which overload of the method was intended to be resolved. /// </remarks> /// <param name="hub">Hub to search for the specified <paramref name="method"/> on.</param> /// <param name="method">The method name to search for.</param> /// <param name="descriptor">If successful, the <see cref="MethodDescriptor"/> that was resolved.</param> /// <param name="parameters">The set of parameters that will be used to help locate a specific overload of the specified <paramref name="method"/>.</param> /// <returns>True if the method matching the name/parameter set is found on the hub, otherwise false.</returns> public bool TryGetMethod(HubDescriptor hub, string method, out MethodDescriptor descriptor, IList<IJsonValue> parameters) { string hubMethodKey = BuildHubExecutableMethodCacheKey(hub, method, parameters); if (!_executableMethods.TryGetValue(hubMethodKey, out descriptor)) { IEnumerable<MethodDescriptor> overloads; if (FetchMethodsFor(hub).TryGetValue(method, out overloads)) { var matches = overloads.Where(o => o.Matches(parameters)).ToList(); // If only one match is found, that is the "executable" version, otherwise none of the methods can be returned because we don't know which one was actually being targeted descriptor = matches.Count == 1 ? matches[0] : null; } else { descriptor = null; } // If an executable method was found, cache it for future lookups (NOTE: we don't cache null instances because it could be a surface area for DoS attack by supplying random method names to flood the cache) if (descriptor != null) { _executableMethods.TryAdd(hubMethodKey, descriptor); } } return descriptor != null; }
public bool TryGetMethod(HubDescriptor hub, string method, out MethodDescriptor descriptor, params IJsonValue[] parameters) { descriptor = new MethodDescriptor { Hub = hub, Invoker = (h, args) => { var pkg = ((dynamic)args[0]); //default to broadcast only to others IClientProxy proxy = h.Clients.Others; if (pkg.recipients == "ALL") proxy = h.Clients.All; else if (pkg.recipients == "SELF") proxy = h.Clients.Caller; var _appId = h.Context.ConnectionId; dynamic _op = false; //How to deal with concurrent requests? //This is the derby/racer conflict resolution problem //Like -- what if two users perform an update at the same time? //For now, the broadcast is just sent to all.... //but an in-out pub/sub redis store that caches the requests //and only executes the LAST one might be a simple solution if (pkg.appBoxr != null) { var _clientId = pkg.clientId.ToString(); var _repo = GlobalHost.DependencyResolver.Resolve<IDataLayer>(); var appBoxr = (dynamic)pkg.appBoxr; string process = appBoxr.process.top.ToString(); if (process == "GET") { _op = _repo.Get(appBoxr.queries); } else if (process == "SAVE") { _op = _repo.Save(appBoxr.models.ToString()); } else if (process == "DELETE") { _op = _repo.Delete(new { ids = appBoxr.ids.ToString(), collection = appBoxr.collection }); } } //result is always 2nd param of GET SAVE and DELETE ops return proxy.Invoke(method, pkg, _op); }, Name = method, Attributes = new List<AuthAttribute>() { new AuthAttribute() }, Parameters = Enumerable.Range(0, parameters.Length).Select(i => new Microsoft.AspNet.SignalR.Hubs.ParameterDescriptor { Name = "p_" + i, ParameterType = typeof(object) }).ToArray(), ReturnType = typeof(Task) }; return true; }
/// <summary> /// Resolves method parameter values based on provided objects. /// </summary> /// <param name="method">Method descriptor.</param> /// <param name="values">List of values to resolve parameter values from.</param> /// <returns>Array of parameter values.</returns> public virtual IList<object> ResolveMethodParameters(MethodDescriptor method, IList<IJsonValue> values) { if (method == null) { throw new ArgumentNullException("method"); } return method.Parameters.Zip(values, ResolveParameter).ToArray(); }
/// <summary> /// 重写以将Default中的Array更改为List,使Args能修改 /// </summary> public override IList<object> ResolveMethodParameters(MethodDescriptor method, IList<IJsonValue> values) { method.CheckNotNull("method" ); if (values != null && values.Count > 0) { object value = values.First().ConvertTo(typeof(string)); return new List<object>() { value }; } return method.Parameters.Zip(values, (descriptor, value) => ResolveParameter(descriptor, value)).ToList(); }
private static IEnumerable<HubMethodParameterModel> GetHubMethodParametersInfo(MethodDescriptor hubMethodDescriptor) { var hubMethodParameterDescriptors = hubMethodDescriptor.Parameters; if (hubMethodParameterDescriptors == null || !hubMethodParameterDescriptors.Any()) return null; var hubMethodParameterData = hubMethodParameterDescriptors .Select(hubMethodParameterDescriptor => new HubMethodParameterModel { Name = hubMethodParameterDescriptor.Name, ParameterType = hubMethodParameterDescriptor.ParameterType }) .ToList(); return hubMethodParameterData; }
public bool TryGetMethod(HubDescriptor hub, string method, out MethodDescriptor descriptor, params IJsonValue[] parameters) { descriptor = new MethodDescriptor { Hub = hub, Invoker = (h, args) => { IClientProxy proxy = h.Clients.All; return proxy.Invoke(method, args); }, Name = method, Attributes = new List<AuthAttribute>() { new AuthAttribute() }, Parameters = Enumerable.Range(0, parameters.Length).Select(i => new Microsoft.AspNet.SignalR.Hubs.ParameterDescriptor { Name = "p_" + i, Type = typeof(object) }).ToArray(), ReturnType = typeof(Task) }; return true; }
public static IHubIncomingInvokerContext CreateHubIncomingInvokerContext(bool isAuthenticated, string methodName, string hubName = null) { var request = CreateRequest(isAuthenticated); var hub = new Mock<IHub>(); hub.Setup(h => h.Context).Returns(new HubCallerContext(request.Object, "connectionId")); var methodDescriptor = new MethodDescriptor { Name = methodName, Hub = new HubDescriptor { Name = hubName } }; var context = new Mock<IHubIncomingInvokerContext>(); context.Setup(c => c.Hub).Returns(hub.Object); context.Setup(c => c.MethodDescriptor).Returns(methodDescriptor); return context.Object; }
/// <summary> /// Resolves method parameter values based on provided objects. /// </summary> /// <param name="method">Method descriptor.</param> /// <param name="values">List of values to resolve parameter values from.</param> /// <returns>Array of parameter values.</returns> public virtual object[] ResolveMethodParameters(MethodDescriptor method, params IJsonValue[] values) { return method.Parameters.Zip(values, ResolveParameter).ToArray(); }
private Task InvokeHubPipeline(IRequest request, string connectionId, string data, HubRequest hubRequest, IJsonValue[] parameterValues, MethodDescriptor methodDescriptor, TrackingDictionary state, IHub hub) { var args = _binder.ResolveMethodParameters(methodDescriptor, parameterValues); var context = new HubInvokerContext(hub, state, methodDescriptor, args); // Invoke the pipeline return(_pipelineInvoker.Invoke(context) .ContinueWith(task => { if (task.IsFaulted) { return ProcessResponse(state, null, hubRequest, task.Exception); } else { return ProcessResponse(state, task.Result, hubRequest, null); } }) .FastUnwrap()); }
public bool TryGetMethod(HubDescriptor hub, string method, out MethodDescriptor descriptor, params IJsonValue[] parameters) { descriptor = new MethodDescriptor { Hub = hub, Invoker = (h, args) => { var pkg = ((dynamic)args[0]); //default to broadcast only to others IClientProxy proxy = h.Clients.Others; if (pkg.recipients == "ALL") proxy = h.Clients.All; else if (pkg.recipients == "SELF") proxy = h.Clients.Caller; var _appId = h.Context.ConnectionId; if (pkg.appBoxr != null) { var _clientId = pkg.clientId.ToString(); var _repo = GlobalHost.DependencyResolver.Resolve<IDataLayer>(); var appBoxr = pkg.appBoxr; var _op = false; string _model = ""; string _passedModel = ((dynamic)appBoxr).model.ToString().Replace(Environment.NewLine, ""); string process = ((dynamic)appBoxr).process.ToString(); string _pageId = ((dynamic)appBoxr).pageId.ToString(); if (process == "GET") _model = _repo.Get(new { applicationId = _appId, pageId = _pageId, clientId = _clientId }); else if (process == "SAVE") _op = _repo.Save(new { applicationId = _appId, pageId = _pageId, clientId = _clientId }, _passedModel); else if (process == "DELETE") _op = _repo.Delete(new { applicationId = _appId, pageId = _pageId, clientId = _clientId }); args.ToList().Add(JsonConvert.SerializeObject(new { operationResult = _op, model = _model })); } return proxy.Invoke(method, args); }, Name = method, Attributes = new List<AuthAttribute>() { new AuthAttribute() }, Parameters = Enumerable.Range(0, parameters.Length).Select(i => new Microsoft.AspNet.SignalR.Hubs.ParameterDescriptor { Name = "p_" + i, Type = typeof(object) }).ToArray(), ReturnType = typeof(Task) }; return true; }