internal void Route(MqttRouteContext routeContext) { for (var i = 0; i < Routes.Length; i++) { Routes[i].Match(routeContext); if (routeContext.Handler != null) { return; } } }
public void Route_Miss() { // Arrange var routes = new string[] { "super/awesome", "super/cool", "other/route" }; var MockMethod = Type.GetType("MQTTnet.AspNetCore.AttributeRouting.Tests.RouteTableTests").GetMethod("Route_Match", BindingFlags.Public); var MockMethod2 = Type.GetType("MQTTnet.AspNetCore.AttributeRouting.Tests.RouteTableTests").GetMethod("Route_Constructor", BindingFlags.Public); var MockRoutes = new MqttRoute[] { new MqttRoute( new RouteTemplate(routes[0], new List <TemplateSegment>() { new TemplateSegment(routes[0], "super", false), new TemplateSegment(routes[0], "awesome", false), }), MockMethod, new string[] { }), new MqttRoute( new RouteTemplate(routes[1], new List <TemplateSegment>() { new TemplateSegment(routes[1], "super", false), new TemplateSegment(routes[1], "cool", false), }), MockMethod2, new string[] { }), new MqttRoute( new RouteTemplate(routes[2], new List <TemplateSegment>() { new TemplateSegment(routes[2], "other", false), new TemplateSegment(routes[2], "route", false), }), MockMethod2, new string[] { }), }; var context = new MqttRouteContext("super/miss"); // Act var MockTable = new MqttRouteTable(MockRoutes); MockTable.Route(context); // Assert Assert.IsNull(context.Handler); }
internal async Task OnIncomingApplicationMessage(AspNetMqttServerOptionsBuilder options, MqttApplicationMessageInterceptorContext context) { // Don't process messages sent from the server itself. This avoids footguns like a server failing to publish // a message because a route isn't found on a controller. if (context.ClientId == null) { return; } var routeContext = new MqttRouteContext(context.ApplicationMessage.Topic); routeTable.Route(routeContext); if (routeContext.Handler == null) { // Route not found logger.LogDebug($"Rejecting message publish because '{context.ApplicationMessage.Topic}' did not match any known routes."); context.AcceptPublish = false; } else { using (var scope = options.ServiceProvider.CreateScope()) { Type?declaringType = routeContext.Handler.DeclaringType; if (declaringType == null) { throw new InvalidOperationException($"{routeContext.Handler} must have a declaring type."); } var classInstance = typeActivator.CreateInstance <object>(scope.ServiceProvider, declaringType); // Potential perf improvement is to cache this reflection work in the future. var activateProperties = declaringType.GetRuntimeProperties() .Where((property) => { return (property.IsDefined(typeof(MqttControllerContextAttribute)) && property.GetIndexParameters().Length == 0 && property.SetMethod != null && !property.SetMethod.IsStatic); }) .ToArray(); if (activateProperties.Length == 0) { logger.LogDebug($"MqttController '{declaringType.FullName}' does not have a property that can accept a controller context. You may want to add a [{nameof(MqttControllerContextAttribute)}] to a pubilc property."); } var controllerContext = new MqttControllerContext() { MqttContext = context, MqttServer = scope.ServiceProvider.GetRequiredService <IMqttServer>() }; for (int i = 0; i < activateProperties.Length; i++) { PropertyInfo property = activateProperties[i]; property.SetValue(classInstance, controllerContext); } ParameterInfo[] parameters = routeContext.Handler.GetParameters(); context.AcceptPublish = true; if (parameters.Length == 0) { await HandlerInvoker(routeContext.Handler, classInstance, null).ConfigureAwait(false); } else { object?[] paramArray; try { paramArray = parameters.Select(p => MatchParameterOrThrow(p, routeContext.Parameters)).ToArray(); await HandlerInvoker(routeContext.Handler, classInstance, paramArray).ConfigureAwait(false); } catch (ArgumentException ex) { logger.LogError(ex, $"Unable to match route parameters to all arguments. See inner exception for details."); context.AcceptPublish = false; } catch (TargetInvocationException ex) { logger.LogError(ex.InnerException, $"Unhandled MQTT action exception. See inner exception for details."); // This is an unandled exception from the invoked action context.AcceptPublish = false; } catch (Exception ex) { logger.LogError(ex, "Unable to invoke Mqtt Action. See inner exception for details."); context.AcceptPublish = false; } } } } }