Asp.Net Web Api Grouping And Versioning In Swagger Complete Guide

 Last Update:2025-06-23T00:00:00     .NET School AI Teacher - SELECT ANY TEXT TO EXPLANATION.    9 mins read      Difficulty-Level: beginner

Understanding the Core Concepts of ASP.NET Web API Grouping and Versioning in Swagger

ASP.NET Web API Grouping and Versioning in Swagger

Swagger, now known as OpenAPI, is a powerful tool for designing, building, and documenting RESTful web services. When developing ASP.NET Web APIs that involve multiple services and versions, organizing them effectively becomes crucial. Swagger provides mechanisms to group and version these APIs, making them easier to manage and understand.

Grouping in Swagger

Grouping in Swagger helps organize different API endpoints logically. When APIs are grouped, it becomes easier for developers and consumers to navigate through the documentation, find related endpoints, and understand the overall structure of the API.

  • Attributes for Grouping: ASP.NET Web API uses custom attributes to facilitate grouping. The most commonly used attribute is [ApiExplorerSettings], which includes the GroupName property.
[ApiExplorerSettings(GroupName = "v1")]
public class ValuesControllerV1 : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return Ok(new { Version = "v1", Message = "Hello from v1" });
    }
}
  • Configuration in Swagger: In the Startup.cs file, configure Swagger to include the groups by adding SwaggerDoc entries for each group.
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "API v1", Version = "v1" });
        c.SwaggerDoc("v2", new OpenApiInfo { Title = "API v2", Version = "v2" });
    });
}
  • Swagger UI Configuration: The Swagger UI can be configured to show the different groups using the DocInclusionPredicate method. This method helps filter and include the correct group in the UI.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseRouting();
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.RoutePrefix = string.Empty;
        c.DocExpansion(DocExpansion.List);
        c.DocumentTitle = "My API Documentation";

        foreach (var description in app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>().ApiVersionDescriptions)
        {
            c.SwaggerEndpoint($"swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
        }
    });

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Versioning in Swagger

Versioning is essential for managing changes to APIs without breaking existing functionality. There are several approaches to versioning, including URI-based, header-based, and query-string-based versioning. However, URI-based versioning is the most common and straightforward.

  • Route Versioning: This method involves including the version number in the route template of the controller.

Online Code run

🔔 Note: Select your programming language to check or run code at

💻 Run Code Compiler

Step-by-Step Guide: How to Implement ASP.NET Web API Grouping and Versioning in Swagger

Example: Basic ASP.NET Core Web API with Swagger

First, let's set up a basic ASP.NET Core Web API project with Swashbuckle.

1. Set Up Your Project

Create a new ASP.NET Core Web API project using Visual Studio or the .NET CLI:

dotnet new webapi -n ApiVersioningExample
cd ApiVersioningExample

2. Install Swashbuckle

Next, install the Swashbuckle package if it’s not already included:

dotnet add package Swashbuckle.AspNetCore

3. Configure Swagger in Startup.cs or Program.cs

In ASP.NET Core 6 and later, you configure services and middleware in the Program.cs file directly.

using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();

// Configure Swagger
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API v1"));
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

4. Create a Sample Controller

Add a simple controller SampleController.

using Microsoft.AspNetCore.Mvc;

namespace ApiVersioningExample.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class SampleController : ControllerBase
    {
        [HttpGet]
        public IActionResult Get()
        {
            return Ok(new { Message = "Hello from Sample v1!" });
        }
    }
}

If you run this project, Swagger UI will show your SampleController under a single version (v1).

Example: Grouping API Controllers in Swagger

1. Organize Controllers into Folders

Organize your controllers into different folders to reflect grouping. For example:

  • Controllers/GroupOne
  • Controllers/GroupTwo

Inside these folders, add some sample controllers:

Controllers/GroupOne/SampleV1Controller.cs

using Microsoft.AspNetCore.Mvc;

namespace ApiVersioningExample.Controllers.GroupOne
{
    [ApiController]
    [Route("api/[controller]")]
    public class SampleV1Controller : ControllerBase
    {
        [HttpGet]
        public IActionResult Get()
        {
            return Ok(new { Message = "Hello from GroupOne Sample v1!" });
        }
    }
}

Controllers/GroupTwo/SampleV1Controller.cs

using Microsoft.AspNetCore.Mvc;

namespace ApiVersioningExample.Controllers.GroupTwo
{
    [ApiController]
    [Route("api/[controller]")]
    public class SampleV1Controller : ControllerBase
    {
        [HttpGet]
        public IActionResult Get()
        {
            return Ok(new { Message = "Hello from GroupTwo Sample v1!" });
        }
    }
}

2. Update Swagger Configuration

To group these controllers in Swagger, you can use tagging.

// Configure Swagger
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });

    // Tagging Controllers based on Namespace
    c.TagActionsBy(apiDesc =>
    {
        if (apiDesc.TryGetMethodInfo(out MethodInfo methodInfo))
        {
            var namespaceName = methodInfo.DeclaringType.Namespace;
            var groupName = namespaceName.Substring(namespaceName.LastIndexOf('.') + 1);
            return new[] { groupName };
        }
        return new string[] { };
    });

    c.DocInclusionPredicate((version, desc) =>
    {
        return true; // Always include in this version.
    });

    c.OrderActionsBy(apiDesc => $"{apiDesc.ActionDescriptor.RouteValues["action"]}_{apiDesc.HttpMethod}");
});

You might also want to sort or order the actions within each controller to improve the readability.

Example: Implementing API Versioning in Swagger

API versioning is crucial when maintaining compatibility with various clients over time. ASP.NET Core provides built-in support for API versioning.

1. Install API Versioning Package

You need to install the Microsoft.AspNetCore.Mvc.Versioning package:

dotnet add package Microsoft.AspNetCore.Mvc.Versioning

2. Configure API Versioning in Program.cs

Enable API versioning and set up Swagger accordingly.

using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Versioning;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();

// Configure API Versioning
builder.Services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new ApiVersion(1, 0);
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.ReportApiVersions = true;
    options.ApiVersionReader = new UrlSegmentApiVersionReader(); // v{version}
});

// Configure Versioned Swagger
builder.Services.AddVersionedApiExplorer(options =>
{
    options.GroupNameFormat = "'v'VVV";
});

builder.Services.ConfigureOptions<ConfigureSwaggerOptions>();

// Configure Swagger
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    var provider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
    foreach (var description in provider.ApiVersionDescriptions)
    {
        app.UseSwagger();
        app.UseSwaggerUI(options =>
        {
            options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json",
                $"My API {description.GroupName.ToUpperInvariant()}");
        });
    }
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Create an options class to customize the Swagger generation:

ConfigureSwaggerOptions.cs

using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace ApiVersioningExample
{
    public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
    {
        readonly IApiVersionDescriptionProvider _provider;

        public ConfigureSwaggerOptions(
            IApiVersionDescriptionProvider provider) => 
            _provider = provider;

        public void Configure(SwaggerGenOptions options)
        {
            foreach (var description in _provider.ApiVersionDescriptions)
            {
                options.SwaggerDoc(description.GroupName, CreateVersionInfo(description));
            }
        }

        static OpenApiInfo CreateVersionInfo(ApiVersionDescription description)
        {
            var info = new OpenApiInfo()
            {
                Title = "My API",
                Version = description.ApiVersion.ToString(),
                Description = "A simple ASP.NET Core web API demonstrating Swagger and versioning."
            };

            if (description.IsDeprecated)
            {
                info.Description += " This API version has been deprecated.";
            }

            return info;
        }
    }
}

3. Update Controllers to Support API Versioning

Modify your sample controllers to include versioning attributes.

Controllers/GroupOne/SampleV1Controller.cs

using Microsoft.AspNetCore.Mvc;

namespace ApiVersioningExample.Controllers.GroupOne
{
    [ApiController]
    [ApiVersion("1.0")]
    [Route("api/v{version:apiVersion}/[controller]")]
    public class SampleV1Controller : ControllerBase
    {
        [HttpGet]
        [MapToApiVersion("1.0")] // Maps this endpoint specifically to v1.0
        public IActionResult Get()
        {
            return Ok(new { Message = "Hello from GroupOne Sample v1!" });
        }
    }
}

Controllers/GroupTwo/SampleV1Controller.cs

using Microsoft.AspNetCore.Mvc;

namespace ApiVersioningExample.Controllers.GroupTwo
{
    [ApiController]
    [ApiVersion("1.0")]
    [Route("api/v{version:apiVersion}/[controller]")]
    public class SampleV1Controller : ControllerBase
    {
        [HttpGet]
        [MapToApiVersion("1.0")] // Maps this endpoint specifically to v1.0
        public IActionResult Get()
        {
            return Ok(new { Message = "Hello from GroupTwo Sample v1!" });
        }
    }
}

4. Run Your Project

Run your project and navigate to the Swagger UI. You should see separate versions (v1) for each controller grouped based on their namespace.

Each endpoint should now appear under its respective version, making it easier for consumers to understand what is available and in which version.

Top 10 Interview Questions & Answers on ASP.NET Web API Grouping and Versioning in Swagger

Top 10 Questions and Answers on ASP.NET Web API Grouping and Versioning with Swagger

1. How can I group APIs in Swagger?

Answer: Grouping APIs in Swagger can help organize your documentation, making it easier to understand and navigate. You can achieve this by using action filters or attributes within your ASP.NET Web API project. One common method is to use the [SwaggerTag] attribute in Swashbuckle (the popular Swagger tool for .NET). This attribute allows you to specify a tag name that groups your actions or controllers.

Example:

[SwaggerTag("User Management API")]
public class UsersController : ControllerBase 
{
    // User management actions
}

Another approach is to implement a custom IDocumentFilter that modifies the Swagger document and groups APIs into different tags based on some criteria.

2. Can I group multiple controllers together under one tag in Swagger?

Answer: Yes, you can group multiple controllers under one tag in Swagger. Just apply the same [SwaggerTag] attribute to each controller you wish to include in the group.

For example, if you have two controllers AccountsController and ProfilesController, and want them grouped under "User Management API," you can do:

[SwaggerTag("User Management API")]
public class AccountsController : ControllerBase 
{
    // Actions related to accounts
}

[SwaggerTag("User Management API")]
public class ProfilesController : ControllerBase 
{
    // Actions related to profiles
}

This will ensure that both Accounts and Profiles are listed under the same section (tag) in the Swagger-generated UI.

3. What's the best way to version an ASP.NET Web API?

Answer: API versioning is crucial for maintaining backward compatibility and ensuring that clients don't break when new versions of the API are released. In ASP.NET Core, Microsoft provides support for API versioning through the Microsoft.AspNetCore.Mvc.Versioning package. The most common ways to implement versioning are URL-based and Header-based(version in Accept header).

URL-based versioning:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers().RequireAuthorization()
            .WithMetadata(new ApiVersionAttribute(1, 0));
});

The routes would look like https://example.com/api/v1/SomeController/SomeAction.

Header-based versioning:

services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new ApiVersion(1, 0);
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.ReportApiVersions = true;

    options.ApiVersionReader = new HeaderApiVersionReader("api-version");
});

services.AddVersionedApiExplorer(options =>
{
    options.GroupNameFormat = "'v'VVV";
    options.SubstituteApiVersionInUrl = true;
});

Clients would need to include the version number in the Accept header like Accept: application/json;version=1.0.

4. How can I display multiple version of APIs in Swagger?

Answer: To display multiple versions of APIs in Swagger, you need to set up versioned API explorer properly alongside API versioning middleware. Here's how you can configure it:

Install the necessary packages:

Install-Package Microsoft.AspNetCore.Mvc.Versioning
Install-Package Microsoft.AspNetCore.Mvc.VersionedApiExplorer
Install-Package Swashbuckle.AspNetCore

Configure services:

services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new ApiVersion(1, 0);
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.ReportApiVersions = true;

    // Add these lines to enable query string parameters versioning
    options.ApiVersionReader = ApiVersionReader.Combine(
        new QueryStringApiVersionReader(),
        new HeaderApiVersionReader("api-version"));
});

services.AddVersionedApiExplorer(options =>
{
    options.GroupNameFormat = "'v'VVV";
    options.SubstituteApiVersionInUrl = true;
});

services.AddSwaggerGen(options =>
{
    var provider = services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();

    foreach (var description in provider.ApiVersionDescriptions)
    {
        options.SwaggerDoc(description.GroupName, new OpenApiInfo
        {
            Title = $"Your API {description.ApiVersion}",
            Description = "A simple example ASP.NET Core Web API",
            Version = description.ApiVersion.ToString(),
        });
    }

    // Include XML comments to document Swagger API
    string xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    string xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    options.IncludeXmlComments(xmlPath);
});

Finally, configure the Swagger UI to show all APIs:

app.UseSwagger();

app.UseSwaggerUI(c =>
{
    c.RoutePrefix = string.Empty;

    var provider = app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>();
    foreach (var description in provider.ApiVersionDescriptions)
    {
        c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", 
                          description.GroupName.ToUpperInvariant());
    }
});

5. Can I version my API using Media Types?

Answer: While media type versioning isn't directly supported by default, ASP.NET Core can be extended to handle versioning through Accept headers specifying custom media types. This method adds version info to the Accept header, allowing the server to return the appropriate versioned response:

services.AddApiVersioning(options =>
{
    options.ApiVersionReader = new MediaTypeApiVersionReader("application/vnd.mycompany.someapi.v1.0+json", ...);
});

However, implementing this requires more manual handling compared to header or URL-based strategies. Swagger doesn’t natively support creating separate documents for media-type versions, so additional configuration might be needed.

6. Will using URL-based versioning affect the performance of my web application?

Answer: Mostly not. URL-based versioning is considered lightweight since routing information is explicitly part of the URL. However, consider potential SEO implications as Google and other search engines will treat the versions as different pages.

Performance can be slightly affected due to the additional route parsing overhead compared to header-based versioning but generally negligible unless under extreme load or with very specific performance requirements.

7. Can I use Swagger annotations to customize each endpoint across different versions?

Answer: Yes, you can use Swagger annotations to further customize endpoints across different versions. For example, you may describe a particular endpoint differently in each version or annotate them with examples or usage notes that vary per API version.

Annotations such as [ProducesResponseType], [Produces], [SwaggerResponse], [SwaggerOperation] can be applied within methods to provide detailed information about the responses for a given version.

Example:

[Route("api/v{version:apiVersion}/[controller]")]
public class ValuesController : ControllerBase 
{
    [HttpGet, MapToApiVersion("1.0"),Produces("application/json")]
    [SwaggerOperation(Summary = "Gets list of values for v1.0")]
    public IActionResult GetValues() 
    {
        // Logic for v1.0
    }
    
    [HttpGet, MapToApiVersion("2.0"), Produces("application/json")]
    [SwaggerOperation(Summary = "Gets list of values for v2.0 including new fields")]
    public IActionResult GetValuesV2() 
    {
        // Logic for v2.0
    }
}

8. Do I need to create separate controllers for each version when using ASP.NET Web API versioning?

Answer: Creating separate controllers for each version can be beneficial for clear organization, especially when changes between versions are significant. However, it’s optional and not strictly required. You could implement a single controller with conditional logic based on the version, but this approach can lead to code complexity and potential issues maintaining backward compatibility.

Recommended practice:

  • Use separate controllers for different versions when the changes are substantial.
  • Use attributes (MapToApiVersion) combined with a shared controller when minor adjustments are needed.

9. Is there any tool or library which simplifies implementing versioning along with groupings in Swagger?

Answer: Swashbuckle and its extensions simplify the implementation of API versioning and grouping in Swagger documentation. For detailed scenarios, libraries like Microsoft.AspNetCore.Mvc.Versioning and Microsoft.AspNetCore.Mvc.VersionedApiExplorer provide powerful features to manage versioned APIs efficiently without extensive manual coding. By combining these with Swagger annotations, you can easily organize and document your API with minimal setup efforts.

Here's an overview:

  • Use Microsoft.AspNetCore.Mvc.Versioning: To handle API versioning logic and routing automatically.
  • Integrate Microsoft.AspNetCore.Mvc.VersionedApiExplorer: With Swashbuckle to generate multiple Swagger documents representing different API versions.

These combinations provide out-of-the-box support for documenting and exposing multiple versions of your API in different sections of the Swagger interface.

10. How can I ensure Swagger documentation generated reflects only the current active API version?

Answer: To ensure that Swagger reflects only the current active API version, configure API versioning to default to a specific version and avoid listing older versions in Swagger. Here's an example configuration focusing on version 2.0:

Install packages:

Install-Package Microsoft.AspNetCore.Mvc.Versioning
Install-Package Microsoft.AspNetCore.Mvc.VersionedApiExplorer
Install-Package Swashbuckle.AspNetCore

Configuration in Startup.cs:

services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new ApiVersion(2, 0);
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.ReportApiVersions = true;
    options.ApiVersionReader = new UrlSegmentApiVersionReader();
});

services.AddVersionedApiExplorer(options =>
{
    options.GroupNameFormat = "'v'VVV";
    options.SubstituteApiVersionInUrl = true;
});

services.AddSwaggerGen(options =>
{
    var provider = services.GetRequiredService<IApiVersionDescriptionProvider>();

    options.SwaggerDoc(provider.DefaultApiVersion.GroupName, new OpenApiInfo
    {
        Title = $"Your API {provider.DefaultApiVersion.ApiVersion}",
        Description = "A simple example ASP.NET Core Web API",
        Version = provider.DefaultApiVersion.ApiVersion.ToString(),
    });

    options.DocumentFilter<HideOlderVersionsDocumentFilter>(provider.DefaultApiVersion);
});

public class HideOlderVersionsDocumentFilter : IDocumentFilter
{
    readonly ApiVersion _defaultVersion;

    public HideOlderVersionsDocumentFilter(ApiVersion defaultVersion)
    {
        _defaultVersion = defaultVersion;
    }

    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        // Remove paths which are not matching with the default version group name
        List<string> pathsToRemove = new List<string>();
        foreach (var path in swaggerDoc.Paths)
        {
            bool hasMatchingTag = path.Value.Operations.Any(operation => operation.Key == OperationType.Get
                && operation.Value.Tags.Any(tag => tag.Name.StartsWith($"v{_defaultVersion}" + "."))
            );

            if (!hasMatchingTag)
                pathsToRemove.Add(path.Key);
        }

        foreach (var key in pathsToRemove)
            swaggerDoc.Paths.Remove(key);
    }
}

This setup ensures that Swagger documentation is primarily focused on the latest or default specified version while hiding paths related to older versions unless you intend to expose them.

You May Like This Related .NET Topic

Login to post a comment.