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?
@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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With