Reputation: 30215
I have Swashbuckle annotated code that looks like this:
[Route("api/Subscribers/{id}/[controller]")]
[Route("api/Organizations/{id}/[controller]")]
public class AddressesController : Controller
{
[HttpGet("{aid}")]
[SwaggerResponse(HttpStatusCode.OK, Type = typeof(PostalRecord))]
public async Task<IActionResult> GetAddress(Guid id, Guid aid)
{
//do something
}
I would like to use the GroupActionsBy
customization, as shown in this example, but I want to have the above GetAddress
method simultaneously included into two separate groups that correspond to the two route prefixes shown:
[Route("api/Subscribers/{id}/[controller]")]
[Route("api/Organizations/{id}/[controller]")]
In other words, I want the same method to be listed under both:
How can this be done?
Incidentally, I'm working with ASP.NET Core (dnx46
). If it is not yet possible to do this with the ASP.NET Core version of Swashbucklee, then a full-CLR (Web API 2.2?) example would still be appreciated.
Also, for a more complete story of what I'm trying to do - I have a separate SO post.
The answer given by @venerik got me close to the solution. When I apply his sample code...
[SwaggerOperation(Tags = new []{"Subscribers", "Organizations"})]
...this causes the Swagger listings to look like this:
In short, the "Addresses" endpoints are now appearing under the headings that I want but, as the red arrow indicates, they are now also being "cross-listed"; I don't want the "Subscribers" endpoint being listed under the "Organizations" endpoint.
I'm suspicious that a [SwaggerOperationFilter] might be "the other half" of the answer, if I can make it remove the cross-listed entries. I've not played with that mechanism before.
Also, it is very unfortunate that [SwaggerOperation] can only be applied on methods/actions. I would rather apply it to the class itself:
[Route("api/Subscribers/{id}/[controller]")]
[Route("api/Organizations/{id}/[controller]")]
[SwaggerOperation(Tags = new []{"Subscribers", "Organizations"})]
public class AddressesController : Controller
{
Is there any remedy for this?
Upvotes: 6
Views: 15204
Reputation: 30215
@venerik got me on the right path. But instead of a [SwaggerOperation]
attribute, what I needed was a [SwaggerOperationFilter]
, like this:
public class CategorizeFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
string path = context.ApiDescription.RelativePath;
string segment = path.Split('/')[1];
if (segment != context.ApiDescription.GroupName)
{
operation.Tags = new List<string> { segment };
}
}
}
Then I just decorate my actions as needed:
[Route("api/Subscribers/{id}/[controller]")]
[Route("api/Organizations/{id}/[controller]")]
public class AddressesController : Controller
{
[HttpGet("{aid}")]
[SwaggerOperationFilter(typeof(CategorizeFilter))]
[SwaggerResponse(HttpStatusCode.OK, Type = typeof(PostalRecord))]
public async Task<IActionResult> GetAddress(Guid id, Guid aid)
{
//do something
}
As a consequence, the "Addresses" category completely disappeared from my Swagger UI (good!) and the twin set of endpoint routes are properly divided between "Organizations" and "Subscribers" groups. Perfect!
Upvotes: 6
Reputation: 5904
I do not have experience with ASP.NET Core (yet) but in ASP.NET Web API you can achieve this with the SwaggerOperationAttribute
. You can use this attribute to add tags to operations. For instance, the next piece of code adds the tags Subscribers
and Organizations
:
[SwaggerOperation(Tags = new []{"Subscribers", "Organizations"})]
public async Task<IActionResult> GetAddress(Guid id, Guid aid)
{
//do something
}
Swagger-UI groups operations by tag, so, GetAddress
will get listed under both Subscribers
and Organizations
.
Upvotes: 10