Skip to content

API Documentation

Chris Martinez edited this page May 12, 2017 · 19 revisions

Overview

Adding documentation is often the final, pivotal step in making your versioned services available to clients and fosters their utilization. While there are many approaches to documenting your services, Swagger has quickly become the de facto method for describing REST services. The most popular way to provide Swagger documentation for REST services implemented ASP.NET is using Swashbuckle.

The ASP.NET API versioning project provides several new API explorer implementations that make it easy to add versioning into your Swagger and Swashbuckle configurations. Each of these API explorers do all of the heavy lifting to discover and collate your REST services by API version. They do not directly rely on nor use Swagger or Swashbuckle so that you can use them for other scenarios as well.

Everything you need to add versioned documentation to your ApiController services.

configuration.AddApiVersioning();

// format the version as "'v'major[.minor][-status]"
var apiExplorer = configuration.AddVersionedApiExplorer( o => o.GroupNameFormat = "'v'VVV" );

configuration.EnableSwagger(
    "{apiVersion}/swagger",
    swagger =>
    {
        swagger.MultipleApiVersions(
            ( apiDescription, version ) => apiDescription.GetGroupName() == version,
            info =>
            {
                foreach ( var group in apiExplorer.ApiDescriptions )
                {
                    info.Version( group.Name, $"Sample API {group.ApiVersion}" );
                }
            } );
    } )
 .EnableSwaggerUi( swagger => swagger.EnableDiscoveryUrlSelector() );

Review the sample project for additional setup and configuration options.

Everything you need to add versioned documentation to your ODataController services.

configuration.AddApiVersioning();

var modelBuilder = new VersionedODataModelBuilder( configuration )
{
    ModelBuilderFactory = () => new ODataConventionModelBuilder().EnableLowerCamelCase(),
    ModelConfigurations = { new MyModelConfiguration() }
};
var models = modelBuilder.GetEdmModels();

configuration.MapVersionedODataRoutes( "odata", "api", models );

// format the version as "'v'major[.minor][-status]"
var apiExplorer = configuration.AddODataApiExplorer( o => o.GroupNameFormat = "'v'VVV" );

configuration.EnableSwagger(
    "{apiVersion}/swagger",
    swagger =>
    {
        swagger.MultipleApiVersions(
            ( apiDescription, version ) => apiDescription.GetGroupName() == version,
            info =>
            {
                foreach ( var group in apiExplorer.ApiDescriptions )
                {
                    info.Version( group.Name, $"Sample API {group.ApiVersion}" );
                }
            } );
    } )
 .EnableSwaggerUi( swagger => swagger.EnableDiscoveryUrlSelector() );

Review the sample project for additional setup and configuration options.

Note: This API explorer does not directly tie into the Swashbuckle with OData support because that project also prescribes how API versioning is performed, which is incompatible with this project. This may change or improve in the future.

Everything you need to add versioned documentation to your Controller services.

public void ConfigureServices( IServiceCollection services )
{
    // format the version as "'v'major[.minor][-status]"
    services.AddMvcCore().AddVersionedApiExplorer( o => o.GroupNameFormat = "'v'VVV" );
    services.AddMvc();
    services.AddApiVersioning();
    services.AddSwaggerGen(
        options =>
        {
            var provider = services.BuildServiceProvider()
                                   .GetRequiredService<IApiVersionDescriptionProvider>();

            foreach ( var description in provider.ApiVersionDescriptions )
            {
                options.SwaggerDoc(
                    description.GroupName,
                    new Info()
                    {
                        Title = $"Sample API {description.ApiVersion}",
                        Version = description.ApiVersion.ToString()
                    } );
            }
        } );
}

public void Configure(
    IApplicationBuilder app,
    IHostingEnvironment env,
    ILoggerFactory loggerFactory,
    IApiVersionDescriptionProvider provider )
{
    app.UseMvc();
    app.UseApiVersioning(); // required in 1.1+
    app.UseSwagger();
    app.UseSwaggerUI(
        options =>
        {
            foreach ( var description in provider.ApiVersionDescriptions )
            {
                options.SwaggerEndpoint(
                    $"/swagger/{description.GroupName}/swagger.json",
                    description.GroupName.ToUpperInvariant() );
            }
        } );
}

Review the sample project for additional setup and configuration options.

Swagger and Swashbuckle Integration

There is one part of adding your versioned services to Swagger and Swashbuckle that will require your help - the API version parameter. The API version parameter will vary depending on how you choose to version your services. In fact, it's possible that you allow multiple API version parameters. The API explorer implementations are currently not able to provide this information because the API version parameter is typically not model-bound in requests.

Fortunately, bridging this gap is really easy to achieve using Swashbuckle's extensibility model. The following are simple IOperationFilter implementations that add a description for the API version parameter in the query string, which is the default. You can then add this filter into your configuration, according to the platform you're using, with:

swagger.OperationFilter<ApiVersionParameter>();

ASP.NET Web API or ASP.NET Web API with OData

public class ApiVersionParameter : IOperationFilter
{
    public void Apply(
        Operation operation,
        SchemaRegistry schemaRegistry,
        ApiDescription apiDescription )
    {
        var parameters = operation.parameters;

        if ( parameters == null )
        {
            operation.parameters = parameters = new List<Parameter>();
        }

        var parameter = new Parameter()
        {
            name = "api-version",
            required = true,
            @default = ((VersionedApiDescription) apiDescription).ApiVersion.ToString(),
            @in = "query",
            type = "string",
            description = "The requested API version"
        };

        parameters.Add( parameter );
    }
}

ASP.NET Core

public class ApiVersionParameter : IOperationFilter
{
    public void Apply( Operation operation, OperationFilterContext context )
    {
        var parameters = operation.Parameters;

        if ( parameters == null )
        {
            operation.Parameters = parameters = new List<IParameter>();
        }

        var parameter = new NonBodyParameter()
        {
            Name = "api-version",
            Required = true,
            Default = context.ApiDescription.GetApiVersion().ToString(),
            In = "query",
            Type = "string",
            Description = "The requested API version"
        };

        parameters.Add( parameter );
    }
}
Clone this wiki locally