Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Core 2.1 Swashbuckle - group controllers by area

My situation is rather simple. I have a very large .NET Core 2.1 MVC/WebApi divided into several Areas, representing different modules of my system. I use Swagger (SwashBuckle) and it works very well. My routing are like {area}/{controller}/{action}.

In Swagger UI, every action is grouped into the controllers (standard behaviour). My list of controllers and operations is becoming very very large and hard to grasp. Because of that, i would love if Swagger could divide my controllers into the different areas! Making it possible to collapse area x and every controller within area x.

I really miss this feature or a way to implement it myself! Any ideas are appreciated!

UPDATE

I've tried annotating actions with tags.

This gives me:

- Area 1
    - MethodFromControllerA()
    - MethodFromControllerB()
- Area 2
    - MethodFromControllerC()
    - MethodFromControllerD()

What i want:

- Area 1
    - ControllerA
        - MethodFromControllerA()
    - ControllerB
        - MethodFromControllerB()
- Area 2
    - ControllerC
        - MethodFromControllerC()
    - ControllerD
        - MethodFromControllerD()

Update 2

Another option would be to have several specifications for each of my areas. Like different Swagger UIs for every area. Possible?

like image 922
Casper TL Avatar asked Jan 01 '23 13:01

Casper TL


2 Answers

You first need to install annotations and enable them in your startup:

services.AddSwaggerGen(c =>
{
   c.EnableAnnotations();
});

Then you need to add your "area" as tag to every action.

[SwaggerOperation(
    Tags = new[] { "Area51" }
)]

When you open your swagger ui, it should be automatically grouped by tag now (per default the controller name is the chosen tag).

Further nested grouping of endpoints is currently not possible out of the box with the existing swagger ui generator.

like image 58
B12Toaster Avatar answered Jan 22 '23 06:01

B12Toaster


If your still looking to do this by area name, this is the complete code for doing it in Swashbuckle.AspNetCore:

c.OperationFilter<TagByAreaNameOperationFilter>();
public class TagByAreaNameOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        if (context.ApiDescription.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
        {
            var areaName = controllerActionDescriptor.ControllerTypeInfo.GetCustomAttributes(typeof(AreaAttribute), true)
                .Cast<AreaAttribute>().FirstOrDefault();
            if (areaName != null)
            {
                operation.Tags = new List<OpenApiTag> { new OpenApiTag { Name = areaName.RouteValue } };
            }
            else
            {
                operation.Tags = new List<OpenApiTag> { new OpenApiTag { Name = controllerActionDescriptor.ControllerName } };
            }
        }
    }
}
like image 20
Matt Avatar answered Jan 22 '23 07:01

Matt