-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ Feature - MQTTnet.AspNetCore.AttributeRouting Support #101
Comments
In theory this is supported.
Option 2 would be ideal as an extension to saunter as an MQTT AttributeRouting support package. Unfortunately I don't have any experience with MQTTnet or MQTT AttributeRouting, if you could provide a simple example project (or an existing open source project) using these packages, I am happy to spend some time trying to get it working, and prototype a package implementing option 2 above. I'm not aware of any existing examples using MQTTnet and Saunter. Saunter doesn't provide any message broker, but has support for documenting them by using bindings. |
This also sounds like the cleanest implementation to me!🙂
I just poured my current work into a de-branded example project and invited you as a collaborator, Saunter-MQTTnet-AspNet5-AttributeRouting-ExampleProject I'll continue to try and implement this during my working hours for as long as my boss allows me to work on it, |
Managed to get However the Channel name string conversion (Different for Feel free to reference my project in your Documentation or to include the conversion method in Saunter once I finished it up! |
Thanks, I will take a look over the next few days. |
Ok, there are a couple of issues with Option 2...
We can either
I have a proof of concept using reflection...
public class MqttNetAspNetCoreAttributeRoutingDocumentFilter : IDocumentFilter
{
public void Apply(AsyncApiDocument document, DocumentFilterContext context)
{
var mqttRouteTableFactory = Type.GetType("MQTTnet.AspNetCore.AttributeRouting.MqttRouteTableFactory, MQTTnet.AspNetCore.AttributeRouting");
var mqttRouteTable = Type.GetType("MQTTnet.AspNetCore.AttributeRouting.MqttRouteTable, MQTTnet.AspNetCore.AttributeRouting");
var mqttRoute = Type.GetType("MQTTnet.AspNetCore.AttributeRouting.MqttRoute, MQTTnet.AspNetCore.AttributeRouting");
var mqttRouteTemplate = Type.GetType("MQTTnet.AspNetCore.AttributeRouting.RouteTemplate, MQTTnet.AspNetCore.AttributeRouting");
var mqttTemplateSegment = Type.GetType("MQTTnet.AspNetCore.AttributeRouting.TemplateSegment, MQTTnet.AspNetCore.AttributeRouting");
var create = mqttRouteTableFactory.GetMethod("Create", BindingFlags.Static | BindingFlags.NonPublic, null, CallingConventions.Any,
new[] {typeof(IEnumerable<Assembly>)}, null);
var routeTable = create.Invoke(null, new object[] { new [] {Assembly.GetEntryAssembly() } });
var routes = mqttRouteTable.GetProperty("Routes").GetValue(routeTable);
foreach (var route in (IEnumerable) routes)
{
var template = mqttRoute.GetProperty("Template").GetValue(route);
var segments = mqttRouteTemplate.GetProperty("Segments").GetValue(template);
// MQTTnet route templates are not uri safe, which is required by the asyncapi spec.
var channelItemName = new List<string>();
foreach (var segment in (IEnumerable)segments)
{
var isParameter = (bool) mqttTemplateSegment.GetProperty("IsParameter").GetValue(segment);
var isCatchAll = (bool) mqttTemplateSegment.GetProperty("IsCatchAll").GetValue(segment);
var value = (string) mqttTemplateSegment.GetProperty("Value").GetValue(segment);
channelItemName.Add(isCatchAll ? "#" : isParameter ? "+" : value);
}
var handler = (MethodInfo) mqttRoute.GetProperty("Handler").GetValue(route);
var parameters = handler.GetParameters();
ISchema payload = null;
if (parameters != null && parameters.Any())
{
payload = context.SchemaGenerator.GenerateSchema(parameters.First().ParameterType, context.SchemaRepository);
}
document.Channels.Add(string.Join("/", channelItemName), new ChannelItem
{
Publish = new Operation
{
OperationId = handler.Name,
Summary = handler.GetXmlDocsSummary(),
Message = new Message
{
Payload = payload,
}
}
});
}
}
} If we had access to the MQTTnet RouteTable, it would look something like this...
public class MqttNetAspNetCoreAttributeRoutingDocumentFilter : IDocumentFilter
{
private readonly MqttRouteTable _mqttRouteTable;
public MqttNetAspNetCoreAttributeRoutingDocumentFilter(MqttRouteTable mqttRouteTable)
{
_mqttRouteTable = mqttRouteTable;
}
public void Apply(AsyncApiDocument document, DocumentFilterContext context)
{
foreach (var route in _mqttRouteTable.Routes)
{
// MQTTnet route templates are not uri safe, which is required by the asyncapi spec.
var channelItemName = string.Join("/", route.Template.Segments.Select(s => s.IsCatchAll ? "#" : s.IsParameter ? "+" : s.Value));
var handler = route.Handler;
var parameters = handler.GetParameters();
ISchema payload = null;
if (parameters != null && parameters.Any())
{
payload = context.SchemaGenerator.GenerateSchema(parameters.First().ParameterType, context.SchemaRepository);
}
document.Channels.Add(channelItemName, new ChannelItem
{
Publish = new Operation
{
OperationId = handler.Name,
Summary = handler.GetXmlDocsSummary(),
Message = new Message
{
Payload = payload,
}
}
});
}
}
} I will raise an issue on the MQTTnet.AspNetCore.AttributeRouting project. |
I've been struggling to get
Saunter v0.3.1
to work in combination with:My project has these 2 MQTTnet libraries implemented successfully in ASP.NET 5 now.
I tried to follow Saunters documentation to the letter too. However with MQTTnet there was no need for me to implement
MessageBus(Interface)
s orEvent
(model-like) classes.I can send/receive payloads from the MQTTnet.App client test application, however Saunter AsyncAPI Documentation generation keeps failing, the only thing I see hosted under
/asyncapi/ui/index.html
is the info defined innew AsyncApiDocument()
ofStartup.cs
.Which lead me to wondering:
Any help would be truly welcome!
The text was updated successfully, but these errors were encountered: