NSwag for SignalR
Liero opened this issue · 39 comments
metadata generation for SingalR hubs got some traction here: https://stackoverflow.com/questions/32638158/swagger-like-tool-for-signal-r-hub
I believe that at least the methods that can be invoked on the SignalR hub can be described by swagger, simmilar to WebApi.
Update by @RSuter: You can find a prototype for a SignalR generator here: https://github.com/RSuter/SigSpec
At least the DTOs can be generated for the hub API. But the operations (swagger) and clients (ts) must be different...
Maybe also interfaces?
public class ChatHub : Hub
{
public void Send(string name, string message)
{
// Call the broadcastMessage method to update clients.
Clients.All.broadcastMessage(name, message);
}
public IEnumerable<Message> GetAllMessages()
{
return _messages;
}
}
[GeneratedCode("NSwag")]
interface IChatClient
{
public Task SendAsync(string name, string message, CancellationToken token = nulll);
public Task<Message> GetAllMessagesAsync(CancellationToken token = nulll);
}
not sure however, how the operations could be described in swagger file
I think swagger is not the correct format - and also it cannot be misused for that... But these endpoints are not really RESTful callable...
The optimal solution would be to define a new specification (ie SignalRSpec) and write a new library which generates this spec and code for it using NJsonSchema (like NSwag does).
Well, I guess this specification should be done by microsoft. What do you think? Should we request it on uservoice?
Did you create a uservoice?
Not yet. Would you? I will vote for it. Your voice may be louder than mine :)
Are you/anyone still interested in this?
Yes, I definitely am.
Though I'm not 100% convinced this would fit within the Swagger scope.
Nope, would be a new spec. But we could share a lot of code...
Something like:
{
"hubs": { // the server side hubs => implemented on server, generated as ChatHub for client
"Chat": {
"description": "Foo",
"operations": {
// dictionary of name/operation
}
}
},
"callbacks": { // the client side callbacks (dictionary of name/operation) => implemented as handlers on client
"Send": {
"parameters": {
"a": {
"description": "First parameter.",
// ...JSON Schema
"type": "string"
},
"b": {
// ...JSON Schema
"$ref": "#/definitions/Foo"
}
},
"result": {
// ...JSON Schema
}
}
}
"definitions": {
...
}
}
This would be only for SingnalR Core. My open questions:
- Are the callbacks per hub or global (as in the sample)
- How can we determine the callbacks - is there an interface for them on the server?
I've created an experiment: https://github.com/RSuter/SigSpec
Just start SigSpec.Console...
I dont like the name, do you have a better name for it?
I'm afraid I don't have the time at the moment to delve into this. I would really love to though.
I'm interested in this as well. Has there been any further work done?
There was no more work on this, but i'm open to push this further (SigSpec)
I dont like the name, do you have a better name for it?
SignalR Spec?
BTW, I hope this will work with new SignalR for .NET Core (2.1) that will be released soon
Yep, we have to upgrade the project to ASP.NET Core 2.1 but i dont see why it wouldn't work with the latest versions with some minor fixes...
The bigger part is building all the tooling around that (CLI, etc.) but maybe we can just integrate it into the NSwag tooling so we can share all this infrastructure...
I agree it should just be part of NSwag tooling. We use SignalR side by side with a Web API so generating client code for the whole API at once would be ideal.
At once will not be possible as a web api is described by a swagger spec and a signalr endpoint by something else (eg signalr spec). Is it a requirement to share dtos?
Sharing DTO could be achieved by feature known from good old WCF "Reuse type in referenced assemblies" what do you think? Or maybe we could optionally specify other spec files, whose DTO will be excluded, or included
Alternatively, most powerful approach is the one used in EF Core, where you can specify assembly which will be used to scan for customizations, e.g. something like this:
public class MyCustomDesignTimeServices : IDesignTimeServices
{
public void ConfigureDesignTimeServices(IServiceCollection services)
{
services.AddSingleton<IPluralizer, HumanizerToIPluralizerAdapter>();
}
}
The main problem is that we mostly dont know the referenced assemblies, but atm you can manually exclude dtos (ExcludedDtoTypes and AdditionalNamespaceUsages). I’m talking about the problem that the api and signalr endpoint might expose the same dto and thus it is generated twice (we have two independent specs).
@RSuter: Is it a problem to define the assemblies in CLI argument? (Yes, i'm talking about the same problem)
We don't need to reuse DTOs.
I understand the underlying specs would be different, but if both were defined in the the same .nswag config file then the nswag tool should be able to generate clients for both in a single step, no?
The problem is that ATM the .nswag file can contain only one pipeline and it is swagger based (swagger gen -> swagger spec -> code gen). So it has to be enhanced with multiple pipelines with support for other spec types... lot of work and possible breaking changes
Ah, gotcha. Well two steps is not the end of the world.
Is it a problem to define the assemblies in CLI argument?
Should be doable... (we need an assembly param anyway to load setting extensions)
I’d suggest to first upgrade the project to core 2.1 and improve the client generators, rename project and test it in a custom cli...
Hi everyone!
If anyone still interested in this topic, please take a look at this solution for generating Swagger documentation for SignalR hubs(.NETsupport only):
https://github.com/Dorin-Mocan/SignalRSwaggerGen/wiki
https://www.nuget.org/packages/SignalRSwaggerGen/
Hi
Is this feature dead?
It would be really nice to get SignalR Hubs inside the an ui like the SwaggerUI to be able to test SignalR connections
@truthz03 , check out my comment from above. I have created a package that can help you just DISPLAY your hubs in SwaggerUI, not interact. As for the interaction with hubs via UI, my package does not offer this feature.
@truthz03 , check out my comment from above. I have created a package that can help you just DISPLAY your hubs in SwaggerUI, not interact. As for the interaction with hubs via UI, my package does not offer this feature.
Thanks for your answer. Yes I only need to display my hubs.
Is your link above for NSwag because there is no "services.AddSwaggerGen" method available?
"services.AddSwaggerGen" is only available if I use "Swashbuckle.AspNetCore"
@truthz03 , it's a complementary package for Swagger. You need to install both Swagger and my package. Check out the documentation. And please toss a star for my repo on GitHub in order to support my work. Thank you!
@truthz03 , it's a complementary package for Swagger. You need to install both Swagger and my package. Check out the documentation. And please toss a star for my repo on GitHub in order to support my work. Thank you!
But to use your complementary pacakge I have to install "Swashbuckle.AspNetCore" otherwise I can't call "services.AddSwaggerGen".
I don't want to use "Swashbuckle.AspNetCore" because I use "NSwag.AspNetCore" and call "services.AddOpenApiDocument".
If I add both packages "Swashbuckle.AspNetCore" and "NSwag.AspNetCore" both will serve the web ui on "/swagger" so I have to use 2 different paths. One for the RestApi and "NSwag.AspNetCore" and another for "Swashbuckle.AspNetCore" where I will see ther SignalR Hubs and all RestApis
Or did I missunderstood something?
@truthz03 , SignalRSwaggerGen works in combination with Swashbuckle.AspNetCore, so yes, you'll need to use it as well. You could configure it on a different path and have both Swashbuckle.AspNetCore + SignalRSwaggerGen and NSwag.AspNetCore. Please test if this works for you. I have never tried such scenario.
Is there any latest news?