GithubHelp home page GithubHelp logo

domaindrivendev / swashbuckle.aspnetcore Goto Github PK

View Code? Open in Web Editor NEW
5.2K 186.0 1.3K 4.71 MB

Swagger tools for documenting API's built on ASP.NET Core

License: MIT License

C# 98.96% HTML 0.85% JavaScript 0.11% CSS 0.01% PowerShell 0.07%

swashbuckle.aspnetcore's Introduction

📣 Important notice if you're upgrading between major versions!
* If you're upgrading from 4.x to 5.x, there's several breaking changes to be aware of. See the release notes for details
* If you're making the jump from 3.x to 4.x first, there be dragons there too. See those release notes here

Swashbuckle.AspNetCore

Build status Code coverage OpenSSF Scorecard

NuGet

Swagger tooling for APIs built with ASP.NET Core. Generate beautiful API documentation, including a UI to explore and test operations, directly from your routes, controllers and models.

In addition to its Swagger 2.0 and OpenAPI 3.0 generator, Swashbuckle also provides an embedded version of the awesome swagger-ui that's powered by the generated Swagger JSON. This means you can complement your API with living documentation that's always in sync with the latest code. Best of all, it requires minimal coding and maintenance, allowing you to focus on building an awesome API.

And that's not all ...

Once you have an API that can describe itself in Swagger, you've opened the treasure chest of Swagger-based tools including a client generator that can be targeted to a wide range of popular platforms. See swagger-codegen for more details.

Compatibility

Swashbuckle Version ASP.NET Core Swagger / OpenAPI Spec. swagger-ui Redoc UI
CI >= 2.0.0 2.0, 3.0 5.x.x 2.x.x
6.6.2 >= 2.0.0 2.0, 3.0 5.17.10 2.1.4
5.6.3 >= 2.0.0 2.0, 3.0 3.32.5 2.0.0-rc.40
4.0.0 >= 2.0.0, < 3.0.0 2.0 3.19.5 1.22.2
3.0.0 >= 1.0.4, < 3.0.0 2.0 3.17.1 1.20.0
2.5.0 >= 1.0.4, < 3.0.0 2.0 3.16.0 1.20.0

Getting Started

  1. Install the standard Nuget package into your ASP.NET Core application.

    Package Manager : Install-Package Swashbuckle.AspNetCore
    CLI : dotnet add package Swashbuckle.AspNetCore
    
  2. In the ConfigureServices method of Startup.cs, register the Swagger generator, defining one or more Swagger documents.

    using Microsoft.OpenApi.Models;
    services.AddMvc();
    
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    });
  3. Ensure your API actions and parameters are decorated with explicit "Http" and "From" bindings.

    [HttpPost]
    public void CreateProduct([FromBody]Product product)
    ...
    [HttpGet]
    public IEnumerable<Product> SearchProducts([FromQuery]string keywords)
    ...

    NOTE: If you omit the explicit parameter bindings, the generator will describe them as "query" params by default.

  4. In the Configure method,you should expose the generated Swagger as JSON endpoint(s) by one of following method:

    • Add endpoints if you're using endpoint-based routing.
    app.MapEndpoints(endpoints =>
    {
        // ...
        endpoints.MapSwagger();
    });
    • Insert middleware
    app.UseSwagger();

    At this point, you can spin up your application and view the generated Swagger JSON at "/swagger/v1/swagger.json."

  5. Optionally, insert the swagger-ui middleware if you want to expose interactive documentation, specifying the Swagger JSON endpoint(s) to power it from.

    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("v1/swagger.json", "My API V1");
    });

    Now you can restart your application and check out the auto-generated, interactive docs at "/swagger".

System.Text.Json (STJ) vs Newtonsoft

In versions prior to 5.0.0, Swashbuckle will generate Schema's (descriptions of the data types exposed by an API) based on the behavior of the Newtonsoft serializer. This made sense because that was the serializer that shipped with ASP.NET Core at the time. However, since version 3.0.0, ASP.NET Core introduces a new serializer System.Text.Json (STJ) out-of-the-box, and if you want to continue using Newtonsoft, you need to install a separate package and explicitly opt-in. From Swashbuckle 5.0.0 and beyond a similar pattern is used. That is, out-of-the-box Swashbuckle will assume you're using the STJ serializer and generate Schema's based on its behavior. If you're using Newtonsoft, then you'll need to install a separate Swashbuckle package and explicitly opt-in. This is a required step, regardless of which version of ASP.NET Core you're using.

In summary ...

If you're using System.Text.Json (STJ), then the setup described above will be sufficient, and STJ options/attributes will be automatically honored by the Swagger generator.

If you're using Newtonsoft, then you'll need to install a separate package and explicitly opt-in to ensure that Newtonsoft settings/attributes are automatically honored by the Swagger generator:

Package Manager : Install-Package Swashbuckle.AspNetCore.Newtonsoft
CLI : dotnet add package Swashbuckle.AspNetCore.Newtonsoft
services.AddMvc();

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
services.AddSwaggerGenNewtonsoftSupport(); // explicit opt-in - needs to be placed after AddSwaggerGen()

Swashbuckle, ApiExplorer, and Routing

Swashbuckle relies heavily on ApiExplorer, the API metadata layer that ships with ASP.NET Core. If you're using the AddMvc helper to bootstrap the MVC stack, then ApiExplorer will be automatically registered and SB will work without issue. However, if you're using AddMvcCore for a more paired-down MVC stack, you'll need to explicitly add the ApiExplorer service:

services.AddMvcCore()
    .AddApiExplorer();

Additionally, if you are using conventional routing (as opposed to attribute routing), any controllers and the actions on those controllers that use conventional routing will not be represented in ApiExplorer, which means Swashbuckle won't be able to find those controllers and generate Swagger operations from them. For instance:

app.UseMvc(routes =>
{
   // SwaggerGen won't find controllers that are routed via this technique.
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

You must use attribute routing for any controllers that you want represented in your Swagger document(s):

[Route("example")]
public class ExampleController : Controller
{
    [HttpGet("")]
    public IActionResult DoStuff() { /**/ }
}

Refer to the routing documentation for more information.

Components

Swashbuckle consists of multiple components that can be used together or individually depending on your needs. At its core, there's a Swagger generator, middleware to expose it as JSON endpoints, and a packaged version of the swagger-ui. These 3 packages can be installed with the Swashbuckle.AspNetCore "metapackage" and will work together seamlessly (see Getting Started) to provide beautiful API docs that are automatically generated from your code.

Additionally, there's add-on packages (CLI tools, an alternate UI etc.) that you can optionally install and configure as needed.

"Core" Packages (i.e. installed via Swashbuckle.AspNetCore)

Package Description
Swashbuckle.AspNetCore.Swagger Exposes Swagger JSON endpoints. It expects an implementation of ISwaggerProvider to be registered in the DI container, which it queries to retrieve OpenAPIDocument(s) that are then exposed as serialized JSON
Swashbuckle.AspNetCore.SwaggerGen Injects an implementation of ISwaggerProvider that can be used by the above component. This particular implementation generates OpenApiDocument(s) from your routes, controllers and models
Swashbuckle.AspNetCore.SwaggerUI Exposes an embedded version of the swagger-ui. You specify the API endpoints where it can obtain Swagger JSON, and it uses them to power interactive docs for your API

Additional Packages

Package Description
Swashbuckle.AspNetCore.Annotations Includes a set of custom attributes that can be applied to controllers, actions and models to enrich the generated Swagger
Swashbuckle.AspNetCore.Cli Provides a command line interface for retrieving Swagger directly from a startup assembly, and writing to file
Swashbuckle.AspNetCore.ReDoc Exposes an embedded version of the Redoc UI (an alternative to swagger-ui)

Community Packages

These packages are provided by the open-source community.

Package Description
Swashbuckle.AspNetCore.Filters Some useful Swashbuckle filters which add additional documentation, e.g. request and response examples, authorization information, etc. See its Readme for more details
Unchase.Swashbuckle.AspNetCore.Extensions Some useful extensions (filters), which add additional documentation, e.g. hide PathItems for unaccepted roles, fix enums for client code generation, etc. See its Readme for more details
MicroElements.Swashbuckle.FluentValidation Use FluentValidation rules instead of ComponentModel attributes to augment generated Swagger Schemas
MMLib.SwaggerForOcelot Aggregate documentations over microservices directly on Ocelot API Gateway

Configuration & Customization

The steps described above will get you up and running with minimal setup. However, Swashbuckle offers a lot of flexibility to customize as you see fit. Check out the table below for the full list of options:

Swashbuckle.AspNetCore.Swagger

Change the Path for Swagger JSON Endpoints

By default, Swagger JSON will be exposed at the following route - "/swagger/{documentName}/swagger.json". If necessary, you can change this when enabling the Swagger middleware. Custom routes MUST include the {documentName} parameter.

app.UseSwagger(c =>
{
    c.RouteTemplate = "api-docs/{documentName}/swagger.json";
})

NOTE: If you're using the SwaggerUI middleware, you'll also need to update its configuration to reflect the new endpoints:

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/api-docs/v1/swagger.json", "My API V1");
})

NOTE: If you also need to update the relative path that the UI itself is available on, you'll need to follow the instructions found in Change Relative Path to the UI.

Modify Swagger with Request Context

If you need to set some Swagger metadata based on the current request, you can configure a filter that's executed prior to serializing the document.

app.UseSwagger(c =>
{
    c.PreSerializeFilters.Add((swagger, httpReq) =>
    {
        swagger.Servers = new List<OpenApiServer> { new OpenApiServer { Url = $"{httpReq.Scheme}://{httpReq.Host.Value}" } };
    });
});

The OpenApiDocument and the current HttpRequest are both passed to the filter. This provides a lot of flexibility. For example, you can add an explicit API server based on the "Host" header (as shown), or you could inspect session information or an Authorization header and remove operations from the document based on user permissions.

Serialize Swagger in the 2.0 format

By default, Swashbuckle will generate and expose Swagger JSON in version 3.0 of the specification, officially called the OpenAPI Specification. However, to support backwards compatibility, you can opt to continue exposing it in the 2.0 format with the following option:

app.UseSwagger(c =>
{
    c.SerializeAsV2 = true;
});

Working with Virtual Directories and Reverse Proxies

Virtual directories and reverse proxies can cause issues for applications that generate links and redirects, particularly if the app returns absolute URLs based on the Host header and other information from the current request. To avoid these issues, Swashbuckle uses relative URLs where possible, and encourages their use when configuring the SwaggerUI and Redoc middleware.

For example, to wire up the SwaggerUI middleware, you provide the URL to one or more OpenAPI/Swagger documents. This is the URL that the swagger-ui, a client-side application, will call to retrieve your API metadata. To ensure this works behind virtual directories and reverse proxies, you should express this relative to the RoutePrefix of the swagger-ui itself:

app.UseSwaggerUI(c =>
{
    c.RoutePrefix = "swagger";
    c.SwaggerEndpoint("v1/swagger.json", "My API V1");
});

NOTE: In previous versions of the docs, you may have seen this expressed as a root-relative link (e.g. /swagger/v1/swagger.json). This won't work if your app is hosted on an IIS virtual directory or behind a proxy that trims the request path before forwarding. If you switch to the page-relative syntax shown above, it should work in all cases.

Customizing how the OpenAPI document is serialized

By default, Swashbuckle will serialize the OpenAPI document using the Serialize methods on the OpenAPI document object. If a customized serialization is desired, it is possible to create a custom document serializer that implements the ISwaggerDocumentSerializer interface. This can be set on the SwaggerOptions in the service collection using ConfigureSwagger():

Note

If you plan on using the command line tool to generate OpenAPI specification files, this must be done on the service collection using ConfigureSwagger().

services.ConfigureSwagger(options =>
{
    option.SetCustomDocumentSerializer<CustomDocumentSerializer>();
})

When the command line tool is not used, it can also be done on the application host:

app.UseSwagger(options =>
{
    options.SetCustomDocumentSerializer<CustomDocumentSerializer>();
})

Swashbuckle.AspNetCore.SwaggerGen

Assign Explicit OperationIds

In Swagger, operations MAY be assigned an operationId. This ID MUST be unique among all operations described in the API. Tools and libraries (e.g. client generators) MAY use the operationId to uniquely identify an operation, therefore, it is RECOMMENDED to follow common programming naming conventions.

Auto-generating an ID that matches these requirements, while also providing a name that would be meaningful in client libraries is a non-trivial task and so, Swashbuckle omits the operationId by default. However, if necessary, you can assign operationIds by decorating individual routes OR by providing a custom strategy.

Option 1) Decorate routes with a Name property

[HttpGet("{id}", Name = "GetProductById")]
public IActionResult Get(int id) // operationId = "GetProductById"

Option 2) Provide a custom strategy

// Startup.cs
services.AddSwaggerGen(c =>
{
    ...
    
    // Use method name as operationId
    c.CustomOperationIds(apiDesc =>
    {
        return apiDesc.TryGetMethodInfo(out MethodInfo methodInfo) ? methodInfo.Name : null;
    });
})

// ProductsController.cs
[HttpGet("{id}")]
public IActionResult GetProductById(int id) // operationId = "GetProductById"

NOTE: With either approach, API authors are responsible for ensuring the uniqueness of operationIds across all Operations

List Operation Responses

By default, Swashbuckle will generate a "200" response for each operation. If the action returns a response DTO, then this will be used to generate a schema for the response body. For example ...

[HttpPost("{id}")]
public Product GetById(int id)

Will produce the following response metadata:

responses: {
  200: {
    description: "OK",
    content: {
      "application/json": {
        schema: {
          $ref: "#/components/schemas/Product"
        }
      }
    }
  }
}

Explicit Responses

If you need to specify a different status code and/or additional responses, or your actions return IActionResult instead of a response DTO, you can explicitly describe responses with the ProducesResponseTypeAttribute that ships with ASP.NET Core. For example ...

[HttpPost("{id}")]
[ProducesResponseType(typeof(Product), 200)]
[ProducesResponseType(typeof(IDictionary<string, string>), 400)]
[ProducesResponseType(500)]
public IActionResult GetById(int id)

Will produce the following response metadata:

responses: {
  200: {
    description: "OK",
    content: {
      "application/json": {
        schema: {
          $ref: "#/components/schemas/Product"
        }
      }
    }
  },
  400: {
    description: "Bad Request",
    content: {
      "application/json": {
        schema: {
          type: "object",
          additionalProperties: {
            type: "string"
          }
        }
      }
    }
  },
  500: {
    description: "Internal Server Error",
    content: {}
  }
}

Flag Required Parameters and Schema Properties

In a Swagger document, you can flag parameters and schema properties that are required for a request. If a parameter (top-level or property-based) is decorated with the BindRequiredAttribute or RequiredAttribute, then Swashbuckle will automatically flag it as a "required" parameter in the generated Swagger:

// ProductsController.cs
public IActionResult Search([FromQuery, BindRequired]string keywords, [FromQuery]PagingParams pagingParams)
{
    if (!ModelState.IsValid)
        return BadRequest(ModelState);
    ...
}

// SearchParams.cs
public class PagingParams
{
    [Required]
    public int PageNo { get; set; }

    public int PageSize { get; set; }
}

In addition to parameters, Swashbuckle will also honor the RequiredAttribute when used in a model that's bound to the request body. In this case, the decorated properties will be flagged as "required" properties in the body description:

// ProductsController.cs
public IActionResult Create([FromBody]Product product)
{
    if (!ModelState.IsValid)
        return BadRequest(ModelState);
    ...
}

// Product.cs
public class Product
{
    [Required]
    public string Name { get; set; }

    public string Description { get; set; }
}

Handle Forms and File Uploads

This controller will accept two form field values and one named file upload from the same form:

[HttpPost]
public void UploadFile([FromForm]string description, [FromForm]DateTime clientDate, IFormFile file)

Important note: As per the ASP.NET Core docs, you're not supposed to decorate IFormFile parameters with the [FromForm] attribute as the binding source is automatically inferred from the type. In fact, the inferred value is BindingSource.FormFile and if you apply the attribute it will be set to BindingSource.Form instead, which screws up ApiExplorer, the metadata component that ships with ASP.NET Core and is heavily relied on by Swashbuckle. One particular issue here is that SwaggerUI will not treat the parameter as a file and so will not display a file upload button, if you do mistakenly include this attribute.

Handle File Downloads

ApiExplorer (the ASP.NET Core metadata component that Swashbuckle is built on) DOES NOT surface the FileResult types by default and so you need to explicitly tell it to with the ProducesResponseType attribute (or Produces on .NET 5 or older):

[HttpGet("{fileName}")]
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK, "image/jpeg")]
public FileStreamResult GetFile(string fileName)

Include Descriptions from XML Comments

To enhance the generated docs with human-friendly descriptions, you can annotate controller actions and models with Xml Comments and configure Swashbuckle to incorporate those comments into the outputted Swagger JSON:

  1. Open the Properties dialog for your project, click the "Build" tab and ensure that "XML documentation file" is checked, or add <GenerateDocumentationFile>true</GenerateDocumentationFile> element to the <PropertyGroup> section of your .csproj project file. This will produce a file containing all XML comments at build-time.

    At this point, any classes or methods that are NOT annotated with XML comments will trigger a build warning. To suppress this, enter the warning code "1591" into the "Suppress warnings" field in the properties dialog or add <NoWarn>1591</NoWarn> to the <PropertyGroup> section of your .csproj project file.

  2. Configure Swashbuckle to incorporate the XML comments on file into the generated Swagger JSON:

    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1",
            new OpenApiInfo
            {
                Title = "My API - V1",
                Version = "v1"
            }
         );
    
         var filePath = Path.Combine(System.AppContext.BaseDirectory, "MyApi.xml");
         c.IncludeXmlComments(Assembly.GetExecutingAssembly());
         // or c.IncludeXmlComments(typeof(MyController).Assembly));
    }
  3. Annotate your actions with summary, remarks, param and response tags:

    /// <summary>
    /// Retrieves a specific product by unique id
    /// </summary>
    /// <remarks>Awesomeness!</remarks>
    /// <param name="id" example="123">The product id</param>
    /// <response code="200">Product retrieved</response>
    /// <response code="404">Product not found</response>
    /// <response code="500">Oops! Can't lookup your product right now</response>
    [HttpGet("{id}")]
    [ProducesResponseType(typeof(Product), 200)]
    [ProducesResponseType(404)]
    [ProducesResponseType(500)]
    public Product GetById(int id)
  4. You can also annotate types with summary and example tags:

    public class Product
    {
        /// <summary>
        /// The name of the product
        /// </summary>
        /// <example>Men's basketball shoes</example>
        public string Name { get; set; }
    
        /// <summary>
        /// Quantity left in stock
        /// </summary>
        /// <example>10</example>
        public int AvailableStock { get; set; }
    
    /// <summary>
        /// The sizes the product is available in
        /// </summary>
        /// <example>["Small", "Medium", "Large"]</example>
    public List<string> Sizes { get; set; }
    }
  5. Rebuild your project to update the XML Comments file and navigate to the Swagger JSON endpoint. Note how the descriptions are mapped onto corresponding Swagger fields.

NOTE: You can also provide Swagger Schema descriptions by annotating your API models and their properties with summary tags. If you have multiple XML comments files (e.g. separate libraries for controllers and models), you can invoke the IncludeXmlComments method multiple times and they will all be merged into the outputted Swagger JSON.

Provide Global API Metadata

In addition to "PathItems", "Operations" and "Responses", which Swashbuckle generates for you, Swagger also supports global metadata (see https://swagger.io/specification/#oasObject). For example, you can provide a full description for your API, terms of service or even contact and licensing information:

c.SwaggerDoc("v1",
    new OpenApiInfo
    {
        Title = "My API - V1",
        Version = "v1",
        Description = "A sample API to demo Swashbuckle",
        TermsOfService = new Uri("http://tempuri.org/terms"),
        Contact = new OpenApiContact
        {
            Name = "Joe Developer",
            Email = "[email protected]"
        },
        License = new OpenApiLicense
        {
            Name = "Apache 2.0",
            Url = new Uri("https://www.apache.org/licenses/LICENSE-2.0.html")
        }
    }
);

TIP: Use IntelliSense to see what other fields are available.

Generate Multiple Swagger Documents

With the setup described above, the generator will include all API operations in a single Swagger document. However, you can create multiple documents if necessary. For example, you may want a separate document for each version of your API. To do this, start by defining multiple Swagger docs in Startup.cs:

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API - V1", Version = "v1" });
    c.SwaggerDoc("v2", new OpenApiInfo { Title = "My API - V2", Version = "v2" });
})

Take note of the first argument to SwaggerDoc. It MUST be a URI-friendly name that uniquely identifies the document. It's subsequently used to make up the path for requesting the corresponding Swagger JSON. For example, with the default routing, the above documents will be available at "/swagger/v1/swagger.json" and "/swagger/v2/swagger.json".

Next, you'll need to inform Swashbuckle which actions to include in each document. Although this can be customized (see below), by default, the generator will use the ApiDescription.GroupName property, part of the built-in metadata layer that ships with ASP.NET Core, to make this distinction. You can set this by decorating individual actions OR by applying an application wide convention.

Decorate Individual Actions

To include an action in a specific Swagger document, decorate it with the ApiExplorerSettingsAttribute and set GroupName to the corresponding document name (case sensitive):

[HttpPost]
[ApiExplorerSettings(GroupName = "v2")]
public void Post([FromBody]Product product)

Assign Actions to Documents by Convention

To group by convention instead of decorating every action, you can apply a custom controller or action convention. For example, you could wire up the following convention to assign actions to documents based on the controller namespace.

// ApiExplorerGroupPerVersionConvention.cs
public class ApiExplorerGroupPerVersionConvention : IControllerModelConvention
{
    public void Apply(ControllerModel controller)
    {
        var controllerNamespace = controller.ControllerType.Namespace; // e.g. "Controllers.V1"
        var apiVersion = controllerNamespace.Split('.').Last().ToLower();

        controller.ApiExplorer.GroupName = apiVersion;
    }
}

// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(c =>
        c.Conventions.Add(new ApiExplorerGroupPerVersionConvention())
    );

    ...
}

Customize the Action Selection Process

When selecting actions for a given Swagger document, the generator invokes a DocInclusionPredicate against every ApiDescription that's surfaced by the framework. The default implementation inspects ApiDescription.GroupName and returns true if the value is either null OR equal to the requested document name. However, you can also provide a custom inclusion predicate. For example, if you're using an attribute-based approach to implement API versioning (e.g. Microsoft.AspNetCore.Mvc.Versioning), you could configure a custom predicate that leverages the versioning attributes instead:

c.DocInclusionPredicate((docName, apiDesc) =>
{
    if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo)) return false;

    var versions = methodInfo.DeclaringType
        .GetCustomAttributes(true)
        .OfType<ApiVersionAttribute>()
        .SelectMany(attr => attr.Versions);

    return versions.Any(v => $"v{v.ToString()}" == docName);
});

Exposing Multiple Documents through the UI

If you're using the SwaggerUI middleware, you'll need to specify any additional Swagger endpoints you want to expose. See List Multiple Swagger Documents for more.

Omit Obsolete Operations and/or Schema Properties

The Swagger spec includes a deprecated flag for indicating that an operation is deprecated and should be refrained from use. The Swagger generator will automatically set this flag if the corresponding action is decorated with the ObsoleteAttribute. However, instead of setting a flag, you can configure the generator to ignore obsolete actions altogether:

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

A similar approach can also be used to omit obsolete properties from Schemas in the Swagger output. That is, you can decorate model properties with the ObsoleteAttribute and configure Swashbuckle to omit those properties when generating JSON Schemas:

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

Omit Arbitrary Operations

You can omit operations from the Swagger output by decorating individual actions OR by applying an application wide convention.

Decorate Individual Actions

To omit a specific action, decorate it with the ApiExplorerSettingsAttribute and set the IgnoreApi flag:

[HttpGet("{id}")]
[ApiExplorerSettings(IgnoreApi = true)]
public Product GetById(int id)

Omit Actions by Convention

To omit actions by convention instead of decorating them individually, you can apply a custom action convention. For example, you could wire up the following convention to only document GET operations:

// ApiExplorerGetsOnlyConvention.cs
public class ApiExplorerGetsOnlyConvention : IActionModelConvention
{
    public void Apply(ActionModel action)
    {
        action.ApiExplorer.IsVisible = action.Attributes.OfType<HttpGetAttribute>().Any();
    }
}

// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(c =>
        c.Conventions.Add(new ApiExplorerGetsOnlyConvention())
    );

    ...
}

Customize Operation Tags (e.g. for UI Grouping)

The Swagger spec allows one or more "tags" to be assigned to an operation. The Swagger generator will assign the controller name as the default tag. This is important to note if you're using the SwaggerUI middleware as it uses this value to group operations.

You can override the default tag by providing a function that applies tags by convention. For example, the following configuration will tag, and therefore group operations in the UI, by HTTP method:

services.AddSwaggerGen(c =>
{
    ...
    c.TagActionsBy(api => api.HttpMethod);
};

Change Operation Sort Order (e.g. for UI Sorting)

By default, actions are ordered by assigned tag (see above) before they're grouped into the path-centric, nested structure of the Swagger spec. But, you can change the default ordering of actions with a custom sorting strategy:

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

NOTE: This dictates the sort order BEFORE actions are grouped and transformed into the Swagger format. So, it affects the ordering of groups (i.e. Swagger "PathItems"), AND the ordering of operations within a group, in the Swagger output.

Customize Schema Id's

If the generator encounters complex parameter or response types, it will generate a corresponding JSON Schema, add it to the global components/schemas dictionary, and reference it from the operation description by unique Id. For example, if you have an action that returns a Product type, then the generated schema will be referenced as follows:

responses: {
  200: {
    description: "OK",
    content: {
      "application/json": {
        schema: {
          $ref: "#/components/schemas/Product"
        }
      }
    }
  }
}

However, if it encounters multiple types with the same name but different namespaces (e.g. RequestModels.Product & ResponseModels.Product), then Swashbuckle will raise an exception due to "Conflicting schemaIds". In this case, you'll need to provide a custom Id strategy that further qualifies the name:

services.AddSwaggerGen(c =>
{
    ...
    c.CustomSchemaIds((type) => type.FullName);
};

See #2703 for support for nested types.

Override Schema for Specific Types

Out-of-the-box, Swashbuckle does a decent job at generating JSON Schemas that accurately describe your request and response payloads. However, if you're customizing serialization behavior for certain types in your API, you may need to help it out.

For example, you might have a class with multiple properties that you want to represent in JSON as a comma-separated string. To do this you would probably implement a custom JsonConverter. In this case, Swashbuckle doesn't know how the converter is implemented and so you would need to provide it with a Schema that accurately describes the type:

// PhoneNumber.cs
public class PhoneNumber
{
    public string CountryCode { get; set; }

    public string AreaCode { get; set; }

    public string SubscriberId { get; set; }
}

// Startup.cs
services.AddSwaggerGen(c =>
{
    ...
    c.MapType<PhoneNumber>(() => new OpenApiSchema { Type = "string" });
};

Extend Generator with Operation, Schema & Document Filters

Swashbuckle exposes a filter pipeline that hooks into the generation process. Once generated, individual metadata objects are passed into the pipeline where they can be modified further. You can wire up custom filters to enrich the generated "Operations", "Schemas" and "Documents".

Operation Filters

Swashbuckle retrieves an ApiDescription, part of ASP.NET Core, for every action and uses it to generate a corresponding OpenApiOperation. Once generated, it passes the OpenApiOperation and the ApiDescription through the list of configured Operation Filters.

In a typical filter implementation, you would inspect the ApiDescription for relevant information (e.g. route info, action attributes etc.) and then update the OpenApiOperation accordingly. For example, the following filter lists an additional "401" response for all actions that are decorated with the AuthorizeAttribute:

// AuthResponsesOperationFilter.cs
public class AuthResponsesOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
            .Union(context.MethodInfo.GetCustomAttributes(true))
            .OfType<AuthorizeAttribute>();

        if (authAttributes.Any())
            operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
    }
}

// Startup.cs
services.AddSwaggerGen(c =>
{
    ...
    c.OperationFilter<AuthResponsesOperationFilter>();
};

NOTE: Filter pipelines are DI-aware. That is, you can create filters with constructor parameters and if the parameter types are registered with the DI framework, they'll be automatically injected when the filters are instantiated

Schema Filters

Swashbuckle generates a Swagger-flavored JSONSchema for every parameter, response and property type that's exposed by your controller actions. Once generated, it passes the schema and type through the list of configured Schema Filters.

The example below adds an AutoRest vendor extension (see https://github.com/Azure/autorest/blob/master/docs/extensions/readme.md#x-ms-enum) to inform the AutoRest tool how enums should be modelled when it generates the API client.

// AutoRestSchemaFilter.cs
public class AutoRestSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        var type = context.Type;
        if (type.IsEnum)
        {
            schema.Extensions.Add(
                "x-ms-enum",
                new OpenApiObject
                {
                    ["name"] = new OpenApiString(type.Name),
                    ["modelAsString"] = new OpenApiBoolean(true)
                }
            );
        };
    }
}

// Startup.cs
services.AddSwaggerGen(c =>
{
    ...
    c.SchemaFilter<AutoRestSchemaFilter>();
};

The example below allows for automatic schema generation of generic Dictionary<Enum, TValue> objects. Note that this only generates the swagger; System.Text.Json is not able to parse dictionary enums by default, so you will need a special JsonConverter, like in the .NET docs

// DictionaryTKeyEnumTValueSchemaFilter.cs
public class DictionaryTKeyEnumTValueSchemaFilter : ISchemaFilter
{
  public void Apply(OpenApiSchema schema, SchemaFilterContext context)
  {
    // Only run for fields that are a Dictionary<Enum, TValue>
    if (!context.Type.IsGenericType || !context.Type.GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary<,>)))
    {
return;
    }

    var keyType = context.Type.GetGenericArguments()[0];
    var valueType = context.Type.GetGenericArguments()[1];

    if (!keyType.IsEnum)
    {
return;
    }

    schema.Type = "object";
    schema.Properties = keyType.GetEnumNames().ToDictionary(name => name,
name => context.SchemaGenerator.GenerateSchema(valueType,
  context.SchemaRepository));
  }
}

// Startup.cs
services.AddSwaggerGen(c =>
{
    ...
    // These will be replaced by DictionaryTKeyEnumTValueSchemaFilter, but are needed to avoid an error.
    // You will need one for every kind of Dictionary<,> you have.
    c.MapType<Dictionary<MyEnum, List<string>>>(() => new OpenApiSchema());
    c.SchemaFilter<DictionaryTKeyEnumTValueSchemaFilter>();
};
	

Document Filters

Once an OpenApiDocument has been generated, it too can be passed through a set of pre-configured Document Filters. This gives full control to modify the document however you see fit. To ensure you're still returning valid Swagger JSON, you should have a read through the specification before using this filter type.

The example below provides a description for any tags that are assigned to operations in the document:

public class TagDescriptionsDocumentFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        swaggerDoc.Tags = new List<OpenApiTag> {
            new OpenApiTag { Name = "Products", Description = "Browse/manage the product catalog" },
            new OpenApiTag { Name = "Orders", Description = "Submit orders" }
        };
    }
}

NOTE: If you're using the SwaggerUI middleware, the TagDescriptionsDocumentFilter demonstrated above could be used to display additional descriptions beside each group of Operations.

Add Security Definitions and Requirements

In Swagger, you can describe how your API is secured by defining one or more security schemes (e.g basic, api key, oauth2 etc.) and declaring which of those schemes are applicable globally OR for specific operations. For more details, take a look at the Security Requirement Object in the Swagger spec..

In Swashbuckle, you can define schemes by invoking the AddSecurityDefinition method, providing a name and an instance of OpenApiSecurityScheme. For example you can define an OAuth 2.0 - implicit flow as follows:

// Startup.cs
services.AddSwaggerGen(c =>
{
    ...

    // Define the OAuth2.0 scheme that's in use (i.e. Implicit Flow)
    c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.OAuth2,
        Flows = new OpenApiOAuthFlows
        {
            Implicit = new OpenApiOAuthFlow
            {
                AuthorizationUrl = new Uri("/auth-server/connect/authorize", UriKind.Relative),
                Scopes = new Dictionary<string, string>
                {
                    { "readAccess", "Access read operations" },
                    { "writeAccess", "Access write operations" }
                }
            }
        }
    });
};

NOTE: In addition to defining a scheme, you also need to indicate which operations that scheme is applicable to. You can apply schemes globally (i.e. to ALL operations) through the AddSecurityRequirement method. The example below indicates that the scheme called "oauth2" should be applied to all operations, and that the "readAccess" and "writeAccess" scopes are required. When applying schemes of type other than "oauth2", the array of scopes MUST be empty.

c.AddSwaggerGen(c =>
{
    ...

    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
            },
            new[] { "readAccess", "writeAccess" }
        }
    });
})

If you have schemes that are only applicable for certain operations, you can apply them through an Operation filter. For example, the following filter adds OAuth2 requirements based on the presence of the AuthorizeAttribute:

// SecurityRequirementsOperationFilter.cs
public class SecurityRequirementsOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        // Policy names map to scopes
        var requiredScopes = context.MethodInfo
            .GetCustomAttributes(true)
            .OfType<AuthorizeAttribute>()
            .Select(attr => attr.Policy)
            .Distinct();

        if (requiredScopes.Any())
        {
            operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
            operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });

            var oAuthScheme = new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
            };

            operation.Security = new List<OpenApiSecurityRequirement>
            {
                new OpenApiSecurityRequirement
                {
                    [ oAuthScheme ] = requiredScopes.ToList()
                }
            };
        }
    }
}

NOTE: If you're using the SwaggerUI middleware, you can enable interactive OAuth2.0 flows that are powered by the emitted security metadata. See Enabling OAuth2.0 Flows for more details.

Add Security Definitions and Requirements for Bearer auth

services.AddSwaggerGen(c =>
{
    c.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.Http,
        Scheme = "bearer",
        BearerFormat = "JWT",
        Description = "JWT Authorization header using the Bearer scheme."
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearerAuth" }
            },
            new string[] {}
        }
    });
});

Inheritance and Polymorphism

Swagger / OpenAPI defines the allOf and oneOf keywords for describing inheritance and polymorphism relationships in schema definitions. For example, if you're using a base class for models that share common properties you can use the allOf keyword to describe the inheritance hierarchy. Or, if your serializer supports polymorphic serialization/deserialization, you can use the oneOf keyword to document all the "possible" schemas for requests/responses that vary by subtype.

Enabling Inheritance

By default, Swashbuckle flattens inheritance hierarchies. That is, for derived models, the inherited properties are combined and listed alongside the declared properties. This can cause a lot of duplication in the generated Swagger, particularly when there's multiple subtypes. It's also problematic if you're using a client generator (e.g. NSwag) and would like to maintain the inheritance hierarchy in the generated client models. To work around this, you can apply the UseAllOfForInheritance setting, and this will leverage the allOf keyword to incorporate inherited properties by reference in the generated Swagger:

Circle: {
  type: "object",
  allOf: [
    {
      $ref: "#/components/schemas/Shape"
    }
  ],
  properties: {
    radius: {
      type: "integer",
      format: "int32",
    }
  },
},
Shape: {
  type: "object",
  properties: {
    name: {
      type: "string",
      nullable: true,
    }
  },
}

Enabling Polymorphism

If your serializer supports polymorphic serialization/deserialization and you would like to list the possible subtypes for an action that accepts/returns abstract base types, you can apply the UseOneOfForPolymorphism setting. As a result, the generated request/response schemas will reference a collection of "possible" schemas instead of just the base class schema:

requestBody: {
  content: {
    application/json: {
      schema: {
      oneOf: [
        {
          $ref: "#/components/schemas/Rectangle"
        },
        {
          $ref: "#/components/schemas/Circle"
        },
      ],
    }
  }
}

Detecting Subtypes

As inheritance and polymorphism relationships can often become quite complex, not just in your own models but also within the .NET class library, Swashbuckle is selective about which hierarchies it does and doesn't expose in the generated Swagger. By default, it will pick up any subtypes that are defined in the same assembly as a given base type. If you'd like to override this behavior, you can provide a custom selector function:

services.AddSwaggerGen(c =>
{
    ...

    c.UseAllOfForInheritance();

    c.SelectSubTypesUsing(baseType =>
    {
        return typeof(Startup).Assembly.GetTypes().Where(type => type.IsSubclassOf(baseType));
    })
});

NOTE: If you're using the Swashbuckle Annotations library, it contains a custom selector that's based on the presence of SwaggerSubType attributes on base class definitions. This way, you can use simple attributes to explicitly list the inheritance and/or polymorphism relationships you want to expose. To enable this behavior, check out the Annotations docs.

Describing Discriminators

In conjunction with the oneOf and/or allOf keywords, Swagger / OpenAPI supports a discriminator field on base schema definitions. This keyword points to the property that identifies the specific type being represented by a given payload. In addition to the property name, the discriminator description MAY also include a mapping which maps discriminator values to specific schema definitions.

For example, the Newtonsoft serializer supports polymorphic serialization/deserialization by emitting/accepting a "$type" property on JSON instances. The value of this property will be the assembly qualified type name of the type represented by a given JSON instance. So, to explicitly describe this behavior in Swagger, the corresponding request/response schema could be defined as follows:

components: {
  schemas: {
    Shape: {
      required: [
        "$type"
      ],
      type: "object",
      properties: {
        $type: {
          type": "string"
      },
      discriminator: {
        propertyName: "$type",
        mapping: {
          Rectangle: "#/components/schemas/Rectangle",
          Circle: "#/components/schemas/Circle"
        }
      }
    },
    Rectangle: {
      type: "object",
      allOf: [
        {
          "$ref": "#/components/schemas/Shape"
        }
      ],
      ...
    },
    Circle: {
      type: "object",
      allOf: [
        {
          "$ref": "#/components/schemas/Shape"
        }
      ],
      ...
    }
  }
}

If UseAllOfForInheritance or UseOneOfForPolymorphism is enabled, and your serializer supports (and has enabled) emitting/accepting a discriminator property, then Swashbuckle will automatically generate the corresponding discriminator metadata on base schema definitions.

Alternatively, if you've customized your serializer to support polymorphic serialization/deserialization, you can provide some custom selector functions to determine the discriminator name and corresponding mapping:

services.AddSwaggerGen(c =>
{
    ...

    c.UseOneOfForInheritance();

    c.SelectDiscriminatorNameUsing((baseType) => "TypeName");
    c.SelectDiscriminatorValueUsing((subType) => subType.Name);
});

NOTE: If you're using the Swashbuckle Annotations library, it contains custom selector functions that are based on the presence of SwaggerDiscriminator and SwaggerSubType attributes on base class definitions. This way, you can use simple attributes to explicitly provide discriminator metadata. To enable this behavior, check out the Annotations docs.

Swashbuckle.AspNetCore.SwaggerUI

Change Relative Path to the UI

By default, the Swagger UI will be exposed at "/swagger". If necessary, you can alter this when enabling the SwaggerUI middleware:

app.UseSwaggerUI(c =>
{
    c.RoutePrefix = "api-docs"
}

Change Document Title

By default, the Swagger UI will have a generic document title. When you have multiple Swagger pages open, it can be difficult to tell them apart. You can alter this when enabling the SwaggerUI middleware:

app.UseSwaggerUI(c =>
{
    c.DocumentTitle = "My Swagger UI";
}

Change CSS or JS Paths

By default, the Swagger UI include default CSS and JS, but if you wish to change the path or URL (for example to use a CDN):

app.UseSwaggerUI(c =>
{
    c.StylesPath = "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.10/swagger-ui.min.css";
    c.ScriptBundlePath = "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.10/swagger-ui-bundle.min.js";
    c.ScriptPresetsPath = "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.10/swagger-ui-standalone-preset.min.js";
}

List Multiple Swagger Documents

When enabling the middleware, you're required to specify one or more Swagger endpoints (fully qualified or relative to the UI page) to power the UI. If you provide multiple endpoints, they'll be listed in the top right corner of the page, allowing users to toggle between the different documents. For example, the following configuration could be used to document different versions of an API.

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "V1 Docs");
    c.SwaggerEndpoint("/swagger/v2/swagger.json", "V2 Docs");
}

Apply swagger-ui Parameters

The swagger-ui ships with its own set of configuration parameters, all described here. In Swashbuckle, most of these are surfaced through the SwaggerUI middleware options:

app.UseSwaggerUI(c =>
{
    c.DefaultModelExpandDepth(2);
    c.DefaultModelRendering(ModelRendering.Model);
    c.DefaultModelsExpandDepth(-1);
    c.DisplayOperationId();
    c.DisplayRequestDuration();
    c.DocExpansion(DocExpansion.None);
    c.EnableDeepLinking();
    c.EnableFilter();
    c.EnablePersistAuthorization();
    c.EnableTryItOutByDefault();
    c.MaxDisplayedTags(5);
    c.ShowExtensions();
    c.ShowCommonExtensions();
    c.EnableValidator();
    c.SupportedSubmitMethods(SubmitMethod.Get, SubmitMethod.Head);
    c.UseRequestInterceptor("(request) => { return request; }");
    c.UseResponseInterceptor("(response) => { return response; }");
});

Inject Custom JavaScript

To tweak the behavior, you can inject additional JavaScript files by adding them to your wwwroot folder and specifying the relative paths in the middleware options:

app.UseSwaggerUI(c =>
{
    c.InjectJavascript("/swagger-ui/custom.js");
}

NOTE: The InjectOnCompleteJavaScript and InjectOnFailureJavaScript options have been removed because the latest version of swagger-ui doesn't expose the necessary hooks. Instead, it provides a flexible customization system based on concepts and patterns from React and Redux. To leverage this, you'll need to provide a custom version of index.html as described below.

The custom index sample app demonstrates this approach, using the swagger-ui plugin system provide a custom topbar, and to hide the info component.

Inject Custom CSS

To tweak the look and feel, you can inject additional CSS stylesheets by adding them to your wwwroot folder and specifying the relative paths in the middleware options:

app.UseSwaggerUI(c =>
{
    c.InjectStylesheet("/swagger-ui/custom.css");
}

Customize index.html

To customize the UI beyond the basic options listed above, you can provide your own version of the swagger-ui index.html page:

app.UseSwaggerUI(c =>
{
    c.IndexStream = () => GetType().Assembly
        .GetManifestResourceStream("CustomUIIndex.Swagger.index.html"); // requires file to be added as an embedded resource
});

To get started, you should base your custom index.html on the default version

Enable OAuth2.0 Flows

The swagger-ui has built-in support to participate in OAuth2.0 authorization flows. It interacts with authorization and/or token endpoints, as specified in the Swagger JSON, to obtain access tokens for subsequent API calls. See Adding Security Definitions and Requirements for an example of adding OAuth2.0 metadata to the generated Swagger.

If your Swagger endpoint includes the appropriate security metadata, the UI interaction should be automatically enabled. However, you can further customize OAuth support in the UI with the following settings below. See Swagger-UI documentation for more info:

app.UseSwaggerUI(c =>
{
    c.OAuthClientId("test-id");
    c.OAuthClientSecret("test-secret");
    c.OAuthUsername("test-user");
    c.OAuthRealm("test-realm");
    c.OAuthAppName("test-app");
    c.OAuth2RedirectUrl("url");
    c.OAuthScopeSeparator(" ");
    c.OAuthScopes("scope1", "scope2");
    c.OAuthAdditionalQueryStringParams(new Dictionary<string, string> { { "foo", "bar" }}); 
    c.OAuthUseBasicAuthenticationWithAccessCodeGrant();
    c.OAuthUsePkce();
});

Use client-side request and response interceptors

To use custom interceptors on requests and responses going through swagger-ui you can define them as javascript functions in the configuration:

app.UseSwaggerUI(c =>
{
    c.UseRequestInterceptor("(req) => { req.headers['x-my-custom-header'] = 'MyCustomValue'; return req; }");
    c.UseResponseInterceptor("(res) => { console.log('Custom interceptor intercepted response from:', res.url); return res; }");
});

This can be useful in a range of scenarios where you might want to append local xsrf tokens to all requests for example:

app.UseSwaggerUI(c =>
{
    c.UseRequestInterceptor("(req) => { req.headers['X-XSRF-Token'] = localStorage.getItem('xsrf-token'); return req; }");
});

Swashbuckle.AspNetCore.Annotations

Install and Enable Annotations

  1. Install the following Nuget package into your ASP.NET Core application.

    Package Manager : Install-Package Swashbuckle.AspNetCore.Annotations
    CLI : dotnet add package Swashbuckle.AspNetCore.Annotations
    
  2. In the ConfigureServices method of Startup.cs, enable annotations within in the Swagger config block:

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

Enrich Operation Metadata

Once annotations have been enabled, you can enrich the generated Operation metadata by decorating actions with a SwaggerOperationAttribute.

[HttpPost]

[SwaggerOperation(
    Summary = "Creates a new product",
    Description = "Requires admin privileges",
    OperationId = "CreateProduct",
    Tags = new[] { "Purchase", "Products" }
)]
public IActionResult Create([FromBody]Product product)

Enrich Response Metadata

ASP.NET Core provides the ProducesResponseTypeAttribute for listing the different responses that can be returned by an action. These attributes can be combined with XML comments, as described above, to include human friendly descriptions with each response in the generated Swagger. If you'd prefer to do all of this with a single attribute, and avoid the use of XML comments, you can use SwaggerResponseAttributes instead:

[HttpPost]
[SwaggerResponse(201, "The product was created", typeof(Product))]
[SwaggerResponse(400, "The product data is invalid")]
public IActionResult Create([FromBody]Product product)

Enrich Parameter Metadata

You can annotate "path", "query" or "header" bound parameters or properties (i.e. decorated with [FromRoute], [FromQuery] or [FromHeader]) with a SwaggerParameterAttribute to enrich the corresponding Parameter metadata that's generated by Swashbuckle:

[HttpGet]
public IActionResult GetProducts(
    [FromQuery, SwaggerParameter("Search keywords", Required = true)]string keywords)

Enrich RequestBody Metadata

You can annotate "body" bound parameters or properties (i.e. decorated with [FromBody]) with a SwaggerRequestBodyAttribute to enrich the corresponding RequestBody metadata that's generated by Swashbuckle:

[HttpPost]
public IActionResult CreateProduct(
    [FromBody, SwaggerRequestBody("The product payload", Required = true)]Product product)

Enrich Schema Metadata

You can annotate classes or properties with a SwaggerSchemaAttribute to enrich the corresponding Schema metadata that's generated by Swashbuckle:

[SwaggerSchema(Required = new[] { "Description" })]
public class Product
{
	[SwaggerSchema("The product identifier", ReadOnly = true)]
	public int Id { get; set; }

	[SwaggerSchema("The product description")]
	public string Description { get; set; }

	[SwaggerSchema("The date it was created", Format = "date")]
	public DateTime DateCreated { get; set; }
}

NOTE: In Swagger / OpenAPI, serialized objects AND contained properties are represented as Schema instances, hence why this annotation can be applied to both classes and properties. Also worth noting, "required" properties are specified as an array of property names on the top-level schema as opposed to a flag on each individual property.

Apply Schema Filters to Specific Types

The SwaggerGen package provides several extension points, including Schema Filters (described here) for customizing ALL generated Schemas. However, there may be cases where it's preferable to apply a filter to a specific Schema. For example, if you'd like to include an example for a specific type in your API. This can be done by decorating the type with a SwaggerSchemaFilterAttribute:

// Product.cs
[SwaggerSchemaFilter(typeof(ProductSchemaFilter))]
public class Product
{
    ...
}

// ProductSchemaFilter.cs
public class ProductSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        schema.Example = new OpenApiObject
        {
            [ "Id" ] = new OpenApiInteger(1),
            [ "Description" ] = new OpenApiString("An awesome product")
        };
    }
}

Add Tag Metadata

By default, the Swagger generator will tag all operations with the controller name. This tag is then used to drive the operation groupings in the swagger-ui. If you'd like to provide a description for each of these groups, you can do so by adding metadata for each controller name tag via the SwaggerTagAttribute:

[SwaggerTag("Create, read, update and delete Products")]
public class ProductsController
{
    ...
}

NOTE: This will add the above description specifically to the tag named "Products". Therefore, you should avoid using this attribute if you're tagging Operations with something other than controller name - e.g. if you're customizing the tagging behavior with TagActionsBy.

List Known Subtypes for Inheritance and Polymorphism

If you want to use Swashbuckle's inheritance and/or polymorphism behavior, you can use annotations to explicitly indicate the "known" subtypes for a given base type. This will override the default selector function, which selects all subtypes in the same assembly as the base type, and therefore needs to be explicitly enabled when you enable Annotations:

// Startup.cs
services.AddSwaggerGen(c =>
{
    c.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true);
});

// Shape.cs
[SwaggerSubType(typeof(Rectangle))]
[SwaggerSubType(typeof(Circle))]
public abstract class Shape
{
}

Enrich Polymorphic Base Classes with Discriminator Metadata

If you're using annotations to explicitly indicate the "known" subtypes for a polymorphic base type, you can combine the SwaggerDiscriminatorAttribute with the SwaggerSubTypeAttribute to provide additional metadata about the "discriminator" property, which will then be incorporated into the generated schema definition:

// Startup.cs
services.AddSwaggerGen(c =>
{
    c.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true);
});

// Shape.cs
[SwaggerDiscriminator("shapeType")]
[SwaggerSubType(typeof(Rectangle), DiscriminatorValue = "rectangle")]
[SwaggerSubType(typeof(Circle), DiscriminatorValue = "circle")]
public abstract class Shape
{
    public ShapeType { get; set; }
}

This indicates that the corresponding payload will have a "shapeType" property to discriminate between subtypes, and that property will have a value of "rectangle" if the payload represents a Rectangle type and a value of "circle" if it represents a Circle type. This detail will be described in the generated schema definition as follows:

schema: {
  oneOf: [
    {
      $ref: "#/components/schemas/Rectangle"
    },
    {
      $ref: "#/components/schemas/Circle"
    },
  ],
  discriminator: {
    propertyName: shapeType,
    mapping: {
      rectangle: "#/components/schemas/Rectangle",
      circle: "#/components/schemas/Circle",
    }
  }
}

Swashbuckle.AspNetCore.Cli

Retrieve Swagger Directly from a Startup Assembly

Once your application has been setup with Swashbuckle (see Getting Started), you can use the Swashbuckle CLI tool to retrieve Swagger / OpenAPI JSON directly from your application's startup assembly, and write it to file. This can be useful if you want to incorporate Swagger generation into a CI/CD process, or if you want to serve it from static file at run-time.

It's packaged as a .NET Tool that can be installed and used via the dotnet SDK.

⚠️ The tool needs to load your Startup DLL and its dependencies at runtime. Therefore, you should use a version of the dotnet SDK that is compatible with your application. For example, if your app targets net6.0, then you should use version 6.0.xxx of the SDK to run the CLI tool. If it targets net8.0, then you should use version 8.0.xxx of the SDK and so on.

Using the tool with the .NET SDK

  1. Install as a global tool

    dotnet tool install -g Swashbuckle.AspNetCore.Cli
    
  2. Verify that the tool was installed correctly

    swagger tofile --help
    
  3. Generate a Swagger/ OpenAPI document from your application's startup assembly

    swagger tofile --output [output] [startupassembly] [swaggerdoc]
    

    Where ...

    • [output] is the relative path where the Swagger JSON will be output to
    • [startupassembly] is the relative path to your application's startup assembly
    • [swaggerdoc] is the name of the swagger document you want to retrieve, as configured in your startup class

Using the tool with the .NET 6.0 SDK or later

  1. In your project root, create a tool manifest file:

    dotnet new tool-manifest
    
  2. Install as a local tool

    dotnet tool install Swashbuckle.AspNetCore.Cli
    
  3. Verify that the tool was installed correctly

    dotnet swagger tofile --help
    
  4. Generate a Swagger / OpenAPI document from your application's startup assembly

    dotnet swagger tofile --output [output] [startupassembly] [swaggerdoc]
    

    Where ...

    • [output] is the relative path where the Swagger JSON will be output to
    • [startupassembly] is the relative path to your application's startup assembly
    • [swaggerdoc] is the name of the swagger document you want to retrieve, as configured in your startup class

Use the CLI Tool with a Custom Host Configuration

Out-of-the-box, the tool will execute in the context of a "default" web host. However, in some cases you may want to bring your own host environment, for example if you've configured a custom DI container such as Autofac. For this scenario, the Swashbuckle CLI tool exposes a convention-based hook for your application.

That is, if your application contains a class that meets either of the following naming conventions, then that class will be used to provide a host for the CLI tool to run in.

  • public class SwaggerHostFactory, containing a public static method called CreateHost with return type IHost
  • public class SwaggerWebHostFactory, containing a public static method called CreateWebHost with return type IWebHost

For example, the following class could be used to leverage the same host configuration as your application:

public class SwaggerHostFactory
{
    public static IHost CreateHost()
    {
        return Program.CreateHostBuilder(new string[0]).Build();
    }
}

Swashbuckle.AspNetCore.ReDoc

Change Relative Path to the UI

By default, the Redoc UI will be exposed at "/api-docs". If necessary, you can alter this when enabling the Redoc middleware:

app.UseReDoc(c =>
{
    c.RoutePrefix = "docs"
    ...
}

Change Document Title

By default, the Redoc UI will have a generic document title. You can alter this when enabling the Redoc middleware:

app.UseReDoc(c =>
{
    c.DocumentTitle = "My API Docs";
    ...
}

Apply Redoc Parameters

Redoc ships with its own set of configuration parameters, all described here https://github.com/Rebilly/redoc/blob/main/README.md#redoc-options-object. In Swashbuckle, most of these are surfaced through the Redoc middleware options:

app.UseReDoc(c =>
{
    c.SpecUrl("/v1/swagger.json");
    c.EnableUntrustedSpec();
    c.ScrollYOffset(10);
    c.HideHostname();
    c.HideDownloadButton();
    c.ExpandResponses("200,201");
    c.RequiredPropsFirst();
    c.NoAutoAuth();
    c.PathInMiddlePanel();
    c.HideLoading();
    c.NativeScrollbars();
    c.DisableSearch();
    c.OnlyRequiredInSamples();
    c.SortPropsAlphabetically();
});

Using c.SpecUrl("/v1/swagger.json") multiple times within the same UseReDoc(...) will not add multiple urls.

Inject Custom CSS

To tweak the look and feel, you can inject additional CSS stylesheets by adding them to your wwwroot folder and specifying the relative paths in the middleware options:

app.UseReDoc(c =>
{
    ...
    c.InjectStylesheet("/redoc/custom.css");
}

It is also possible to modify the theme by using the AdditionalItems property, see https://github.com/Rebilly/redoc/blob/main/README.md#redoc-options-object for more information.

app.UseReDoc(c =>
{
    ...
    c.ConfigObject.AdditionalItems = ...
}

Customize index.html

To customize the UI beyond the basic options listed above, you can provide your own version of the Redoc index.html page:

app.UseReDoc(c =>
{
    c.IndexStream = () => GetType().Assembly
        .GetManifestResourceStream("CustomIndex.ReDoc.index.html"); // requires file to be added as an embedded resource
});

To get started, you should base your custom index.html on the default version

swashbuckle.aspnetcore's People

Contributors

alexvaluyskiy avatar andyalm avatar captainsafia avatar cwe1ss avatar danielcrenna avatar davidfowl avatar dependabot[bot] avatar domaindrivendev avatar dougbu avatar dunnymeister avatar eneuman avatar esbenbach avatar gencebay avatar github-actions[bot] avatar jgarciadelanoceda avatar johnkors avatar kant2002 avatar keahpeters avatar martincostello avatar mattfrear avatar mikebeaton avatar mikefh avatar moander avatar nkalfov avatar remcolam avatar simoncropp avatar tomkerkhove avatar vankooch avatar wallymathieu avatar wu-yafeng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swashbuckle.aspnetcore's Issues

XML documentation

Hi there,

This is more of a question than an issue, likely.

I'd like to include my XML documentation comments with my swagger documentation. What's the right way to do this with asp.net vnext?

I have a line like this:
c.IncludeXmlComments(".xml");

But I get a FileNotFoundException, because I'm not actually producing any build outputs.

I'm trying to build my code into a Docker image and deploy it to Rancher. Everything works great, except I don't have the nice XML documentation comments I added to my Controller and Model.

Your project is awesome. Thank you!
Ranj

System.MissingMethodException

Hello,

I was hoping to find out when you guys plan on releasing the Beta 8?

I have a Beta 8 MVC 6 App, and I would love to get Swashbuckle installed. I tried many wasy to try and make the Beta 7 that is on Nuget now work but I keep getting this exception right when services.AddSwagger(); is called.

The Error:

System.MissingMethodException was unhandled by user code
  HResult=-2146233069
  Message=Method not found: 'Microsoft.Framework.DependencyInjection.IServiceCollection Microsoft.Framework.DependencyInjection.OptionsServiceCollectionExtensions.Configure(Microsoft.Framework.DependencyInjection.IServiceCollection, System.Action`1<!!0>, Int32, System.String)'.
  Source=Swashbuckle
  StackTrace:
       at Microsoft.Framework.DependencyInjection.SwaggerServiceCollectionExtensions.AddSwagger(IServiceCollection services)
       at RequestIt.Api.Startup.ConfigureServices(IServiceCollection services) in C:\Users\jwuli\Dropbox\Request It Inc\Application\_Prototype\version-1\API\Working Files\RequestIt.Api\Startup.cs:line 42
  InnerException:

Thanks for any help or news!

beta5 version: rebuild solution

Hello!

Can you, please, update Swashbuckle for beta5?
I use "Microsoft.AspNet.Mvc": "6.0.0-beta5-*" and my dnx version is dnx-clr-win-x86.1.0.0-beta5-11682.

Thank you.

Produces attribute should win over SwaggerResponse attribute defaults

I prefer the Produces attribute which is standard ASP.NET (in vNext) to describe return types rather then swagger-specific SwaggerResponse attribute. Unfortunately, XML comments to specify return types is not supported so currently I have to specify a SwaggerResponse for return types. However if I specify SwaggerResponse then I have to specify a type parameter as well or it's default will overwrite the type in the Produces attribute with an empty-type. This means I have to specify the type multiple times as in the example below which I think is bad practice. I would like to remove the type specifier on the SwaggerResponse if I have a Produces attribute (p.s. and for XML comments to be supported as well - see issue #24)

[Produces(typeof(Employee))]
[SwaggerResponse(System.Net.HttpStatusCode.OK, Type=typeof(Employee))]
[SwaggerResponse(System.Net.HttpStatusCode.NotFound)]

Wrong Namespace for AddSwagger() Extension on RC1

Hallo,

your Namespace for the AddSwagger Extension is wrong for RC1. It was renamed by Microsoft a few weeks ago. Microsoft.Framework.* is now Microsoft.Extensions.*

namespace Microsoft.Framework.DependencyInjection

HAS TO BE

namespace Microsoft.Extensions.DependencyInjection
{
public static class SwaggerServiceCollectionExtensions
{
public static void AddSwagger(this IServiceCollection services)
{

Swagger output is followed by Welcome Page

Hello!

I'm using Ahoy with a couple modifications against beta5. I say that so that you can potentially ignore this bug report since beta5 is still under development.

Anyway, when I hit my Swagger endpoint, I see the swagger json, but it's immediately followed by the ASP.NET Welcome Page content (in the same response).

app.UseSwagger("api/{apiVersion}/swagger.json");

app.UseStatusCodePages();
app.UseErrorPage();
app.UseCors(policy => policy.WithOrigins("http://polykube.io"));
app.UseMvc();
app.UseWelcomePage();

Commenting out the last line allows me to consume the swagger json as I'd expect. Not sure if I've done something wrong, if I'm using it incorrectly, or if it's simply a bug in ASP.NET5.

Null ref in reading ApiDescriptions with null HttpMethod

Steps:

  1. File New Web Application => Web Site
  2. Add reference to swaggerui in project.json
  3. Add swagger/swaggerui to startup.cs
  4. Add the controller pasted below.
  5. hit the /swagger/v1/swagger.json endpoint and see the error pasted below.

Controller:

[Route("Something")]
[Produces("application/json")]
public class AnnotatedController : Controller
{
    [Route("SomethingIndex")]
    public IActionResult Index()
    {
        return View();
    }
}

Call stack with extra info in it:

Swashbuckle.Swagger.SwaggerGenerator.<>c.<CreatePathItem>b__6_0(ApiDescription apiDesc) in SwaggerGenerator.cs
        private PathItem CreatePathItem(IEnumerable<ApiDescription> apiDescriptions, ISchemaRegistry schemaRegistry)
        {
            var pathItem = new PathItem();
            // Group further by http method
            var perMethodGrouping = apiDescriptions
                .GroupBy(apiDesc => apiDesc.HttpMethod.ToLower());
            foreach (var group in perMethodGrouping)
            {
                var httpMethod = group.Key;
                if (group.Count() > 1) throw new NotSupportedException(string.Format(
System.Linq.Lookup`2.Create[TSource](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
System.Linq.GroupedEnumerable`3.GetEnumerator()
Swashbuckle.Swagger.SwaggerGenerator.CreatePathItem(IEnumerable`1 apiDescriptions, ISchemaRegistry schemaRegistry) in SwaggerGenerator.cs
            var pathItem = new PathItem();
            // Group further by http method
            var perMethodGrouping = apiDescriptions
                .GroupBy(apiDesc => apiDesc.HttpMethod.ToLower());
            foreach (var group in perMethodGrouping)
            {
                var httpMethod = group.Key;
                if (group.Count() > 1) throw new NotSupportedException(string.Format(
                    "Not supported by Swagger 2.0: Multiple operations with path '{0}' and method '{1}'.",
                    group.First().RelativePathSansQueryString(), httpMethod));
Swashbuckle.Swagger.SwaggerGenerator.<>c__DisplayClass4_0.<GetSwagger>b__4(IGrouping`2 group) in SwaggerGenerator.cs
                throw new UnknownApiVersion(apiVersion);
            var paths = GetApiDescriptionsFor(apiVersion)
                .Where(apiDesc => !(_options.IgnoreObsoleteActions && apiDesc.IsObsolete()))
                .OrderBy(_options.GroupNameSelector, _options.GroupNameComparer)
                .GroupBy(apiDesc => apiDesc.RelativePathSansQueryString())
                .ToDictionary(group => "/" + group.Key, group => CreatePathItem(group, schemaRegistry));
            var swaggerDoc = new SwaggerDocument
            {
                Info = info,
                Host = _options.Host ?? defaultHost,
                BasePath = _options.BasePath ?? defaultBasePath,
System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector)
Swashbuckle.Swagger.SwaggerGenerator.GetSwagger(String apiVersion, String defaultHost, String defaultBasePath, String[] defaultSchemes) in SwaggerGenerator.cs
            var schemaRegistry = _schemaRegistryFactory();
            var info = _options.ApiVersions.FirstOrDefault(v => v.Version == apiVersion);
            if (info == null)
                throw new UnknownApiVersion(apiVersion);
            var paths = GetApiDescriptionsFor(apiVersion)
                .Where(apiDesc => !(_options.IgnoreObsoleteActions && apiDesc.IsObsolete()))
                .OrderBy(_options.GroupNameSelector, _options.GroupNameComparer)
                .GroupBy(apiDesc => apiDesc.RelativePathSansQueryString())
                .ToDictionary(group => "/" + group.Key, group => CreatePathItem(group, schemaRegistry));
            var swaggerDoc = new SwaggerDocument
Swashbuckle.Application.SwaggerDocsMiddleware.<Invoke>d__5.MoveNext() in SwaggerDocsMIddleware.cs
            if (!RequestingSwaggerDocs(httpContext.Request, out apiVersion))
            {
                await _next(httpContext);
                return;
            }
            var swagger = _swaggerProvider.GetSwagger(apiVersion, null, httpContext.Request.PathBase);
            RespondWithSwaggerJson(httpContext.Response, swagger);
        }
        private bool RequestingSwaggerDocs(HttpRequest request, out string apiVersion)
        {
            apiVersion = null;
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Diagnostics.Entity.DatabaseErrorPageMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNet.Diagnostics.Entity.DatabaseErrorPageMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNet.Diagnostics.ErrorPageMiddleware.<Invoke>d__4.MoveNext()

Beta7, XmlComments

Looks like you changed the way we apply xml comments. The handy IncludeXmlComments has been replaced by the less handy :

options.ModelFilter(new Swashbuckle.Swagger.XmlComments.ApplyXmlTypeComments("pathtoxmlcomments"));
options.ModelFilter(new Swashbuckle.Swagger.XmlComments.ApplyXmlActionComments("pathtoxmlcomments"")));          

the issue is that you left an unintentional new() constraint on the ModelFilter overload which takes an instance as argument. So it won't compile.

BTW, it looks like there is no easy way to configure schemes anymore. I had to write a DocumentFilter. Not sure why remove such feature.

Error generating when there is IFormFile as a parameter

Above I get an error by having an IList in the parameters. This is for allowing file uploads. The stack trace doesn't make sense to me. Anyone have any idea. I haven't stepped into Ahoy's code yet to determine where exactly the error is

ahoy stacktrace

Consumes attribute ignored

Seems that Consumes attribute is ignored and that the generated json is without it. I've see a commented line (148 of DefaultSwaggerProvider.cs) that should handle consumes...

services.AddSwaggerGen(c => {}) not working

Hi,

I am using ASP.Net 5 Swagger for my API, works very good. For Authentication i want to use Oauth2 and tried to replicate the example:

services.AddSwaggerGen(c => { c.AddSecurityDefinition("oauth2", new OAuth2Scheme { Type = "oauth2", Flow = "implicit", AuthorizationUrl = "http://petstore.swagger.io/api/oauth/dialog", Scopes = new Dictionary<string, string> { { "read", "read access" }, { "write", "write access" } } }); c.OperationFilter<AssignSecurityRequirements>(); });

My project.json:

"Swashbuckle.SwaggerGen": "6.0.0-rc1-final", "Swashbuckle.SwaggerUi": "6.0.0-rc1-final"

The example is working, but in my project the extension for services.AddSwaggerGen does not accept any argument. The using statement

using Swashbuckle.SwaggerGen.Generator;
The error is that SwaggerGen does not contain the namespace Generator.

Anything broken in the nuget package?

Could not load file or assembly 'Microsoft.AspNet.Mvc.Formatters.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies.

Runtime exception when starting up an clean ASP.NET MVC 6 site with Swashbuckle 6.0.0-beta7 installed from NuGet.

xxx

Startup.cs:

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
    }

    // This method gets called by a runtime.
    // Use this method to add services to the container
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        // Uncomment the following line to add Web API services which makes it easier to port Web API 2 controllers.
        // You will also need to add the Microsoft.AspNet.Mvc.WebApiCompatShim package to the 'dependencies' section of project.json.
        // services.AddWebApiConventions();

        services.AddSwagger();

        services.ConfigureSwaggerDocument(options =>
        {
            options.SingleApiVersion(new Info
            {
                Version = "v1",
                Title = "Swashbuckle Sample API",
                Description = "A sample API for testing Swashbuckle",
                TermsOfService = "Some terms ..."
            });
        });
        services.ConfigureSwaggerSchema(options =>
        {
            options.DescribeAllEnumsAsStrings = true;
        });
    }

    // Configure is called after ConfigureServices is called.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // Configure the HTTP request pipeline.
        app.UseStaticFiles();

        // Add MVC to the request pipeline.
        app.UseMvc();
        // Add the following route for porting Web API 2 controllers.
        // routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");

        app.UseSwagger();
        app.UseSwaggerUi();
    }
}

Add support for dnxcore50

We should add support for building CoreCLR (dnxcore50).

I was able to prototype it pretty easily by adding this to project.json:

    "frameworks": {
        "dnx451": { },
        "dnxcore50": {
            "dependencies": {
                "System.Xml.XPath": "4.0.0-beta-*"
            }
        }
    }

The only extra dependency needed was xpath. Consider doing the same for the tests.

Doing a dnu restore dnu build will build for both flavors.

BasicApi project doesn't run on kestrel

Tried running this on my Mac. Added a kestrel execution option:
"kestrel": "Microsoft.AspNet.Hosting --server Kestrel --config hosting.ini",

DSA010065:BasicApi mike.borozdin$ dnvm list

Active Version              Runtime Arch OperatingSystem Alias
------ -------              ------- ---- --------------- -----
  *    1.0.0-beta6          mono         linux/darwin    default
DSA010065:BasicApi mike.borozdin$ dnx . kestrel
Microsoft.Framework.Runtime.Roslyn.RoslynCompilationException: /Users/mike.borozdin/src/Ahoy/test/WebSites/BasicApi/Startup.cs(24,13): DNX,Version=v4.5.1 error CS0246: The type or namespace name 'IServiceCollection' could not be found (are you missing a using directive or an assembly reference?)
/Users/mike.borozdin/src/Ahoy/test/WebSites/BasicApi/Startup.cs(49,13): DNX,Version=v4.5.1 error CS0246: The type or namespace name 'IApplicationBuilder' could not be found (are you missing a using directive or an assembly reference?)
/Users/mike.borozdin/src/Ahoy/test/WebSites/BasicApi/Startup.cs(50,13): DNX,Version=v4.5.1 error CS0246: The type or namespace name 'IApplicationBuilder' could not be found (are you missing a using directive or an assembly reference?)
  at Microsoft.Framework.Runtime.Roslyn.RoslynProjectReference.Load (IAssemblyLoadContext loadContext) [0x00000] in <filename unknown>:0 
  at Microsoft.Framework.Runtime.Loader.ProjectAssemblyLoader.Load (System.Reflection.AssemblyName assemblyName, IAssemblyLoadContext loadContext) [0x00000] in <filename unknown>:0 
  at Microsoft.Framework.Runtime.Loader.ProjectAssemblyLoader.Load (System.Reflection.AssemblyName assemblyName) [0x00000] in <filename unknown>:0 
  at dnx.host.LoaderContainer.Load (System.Reflection.AssemblyName assemblyName) [0x00000] in <filename unknown>:0 
  at dnx.host.DefaultLoadContext.LoadAssembly (System.Reflection.AssemblyName assemblyName) [0x00000] in <filename unknown>:0 
  at Microsoft.Framework.Runtime.Loader.AssemblyLoaderCache.GetOrAdd (System.Reflection.AssemblyName name, System.Func`2 factory) [0x00000] in <filename unknown>:0 
  at Microsoft.Framework.Runtime.Loader.LoadContext.LoadAssemblyImpl (System.Reflection.AssemblyName assemblyName) [0x00000] in <filename unknown>:0 
  at Microsoft.Framework.Runtime.Loader.LoadContext.ResolveAssembly (System.Object sender, System.ResolveEventArgs args) [0x00000] in <filename unknown>:0 
  at System.AppDomain.DoAssemblyResolve (System.String name, System.Reflection.Assembly requestingAssembly, Boolean refonly) [0x00000] in <filename unknown>:0 
  at (wrapper managed-to-native) System.AppDomain:LoadAssembly (System.AppDomain,string,System.Security.Policy.Evidence,bool)
  at System.AppDomain.Load (System.Reflection.AssemblyName assemblyRef, System.Security.Policy.Evidence assemblySecurity) [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.AppDomain:Load (System.Reflection.AssemblyName,System.Security.Policy.Evidence)
  at System.AppDomain.Load (System.Reflection.AssemblyName assemblyRef) [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.AppDomain:Load (System.Reflection.AssemblyName)
  at System.Reflection.Assembly.Load (System.Reflection.AssemblyName assemblyRef) [0x00000] in <filename unknown>:0 
  at Microsoft.AspNet.Hosting.Startup.StartupLoader.FindStartupType (System.String startupAssemblyName, IList`1 diagnosticMessages) [0x00000] in <filename unknown>:0 
  at Microsoft.AspNet.Hosting.Internal.HostingEngine.EnsureStartup () [0x00000] in <filename unknown>:0 
  at Microsoft.AspNet.Hosting.Internal.HostingEngine.EnsureApplicationServices () [0x00000] in <filename unknown>:0 
  at Microsoft.AspNet.Hosting.Internal.HostingEngine.Start () [0x00000] in <filename unknown>:0 
  at Microsoft.AspNet.Hosting.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0 
  at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
  at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x00000] in <filename unknown>:0 
  at Microsoft.Framework.Runtime.Common.EntryPointExecutor.Execute (System.Reflection.Assembly assembly, System.String[] args, IServiceProvider serviceProvider) [0x00000] in <filename unknown>:0 
  at Microsoft.Framework.ApplicationHost.Program.ExecuteMain (Microsoft.Framework.Runtime.DefaultHost host, System.String applicationName, System.String[] args) [0x00000] in <filename unknown>:0 
  at Microsoft.Framework.ApplicationHost.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x00000] in <filename unknown>:0 
  at Microsoft.Framework.Runtime.Common.EntryPointExecutor.Execute (System.Reflection.Assembly assembly, System.String[] args, IServiceProvider serviceProvider) [0x00000] in <filename unknown>:0 
  at dnx.host.Bootstrapper.RunAsync (System.Collections.Generic.List`1 args, IRuntimeEnvironment env, System.Runtime.Versioning.FrameworkName targetFramework) [0x00000] in <filename unknown>:0 

Unable to locate System.Xml.XPath >= 4.0.0-beta-23110

First time I've used Swashbuckle, added it into an empty vnext website created from webapi template in Visual Studio 2015 (RTM), got an error whilst restoring the packages in the package manager output "Unable to locate System.Xml.XPath >= 4.0.0-beta-23110".

I found that the most recently published version on the official nuget feed is "4.0.0-beta-23019" (https://www.nuget.org/packages/System.Xml.XPath/4.0.0-beta-23019).

The quick fix is to enable the vnext nightly nuget feed "https://www.myget.org/F/aspnetvnext" in your package sources.

Considering beta5 packages have now been released, is it worth while removing the requirement on the nightly feed?

Setup should be done in the UseSwagger method

Hi,

I'm starting to play with Swashbuckle for mvc6. At the moment, the options are set on the service instead of the application. This blocks a scenario where you would want to have multiple Swashbuckle setup like this:

 app.Map("/api/v1", v1App =>
                               {
                                   v1App.UseMvc();
                                   v1App.UseSwagger();
                               });
 app.Map("/api/v2", v2App =>
                               {
                                   v2App.UseMvc();
                                   v2App.UseSwagger();
                               });

Which would end up with two swagger endpoints, and that's what I want. I don't really care about discoverability of all api versions in my case.

My reason for doing this is that once I'm coding v2 api, I absolutely don't want the v1 api to change. If the swagger file is part of the v1 api and we configure the service instead of the application, this would mean that I have the v1 api swagger and v2 api swagger code in one single place. Adding api distinctions in that case would become increasingly difficult to maintain.

Move ConfigureSwaggerDocument and ConfigureSwaggerSchema from ConfigureServices to Configure in Setup

Currently ConfigureSwaggerDocument and ConfigureSwaggerSchema must be done in Setup.ConfigureServices of the client web project. At this stage the client knows nothing about the execution environment so it need to hardcode a full path the the documentation XML XmlComments file. Not nice!

It would be better if these can be done later in Setup.Configure where it is possible to use dependency injection to get hold of IApplicationEnvironment which allows for calculating where the XML XmlComments file is located relative to the ApplicationBasePath.

Doesn't work with RC2

Swashbuckle throws an exception when calling 'UseSwaggerGen()'.

Exception:

System.NullReferenceException: Object reference not set to an instance of an object.

Source Assembly:

Swashbuckle.SwaggerGen

Stacktrace:

at Microsoft.Extensions.DependencyInjection.SwaggerGenServiceCollectionExtensions.GetJsonSerializerSettings(IServiceProvider serviceProvider)
at Microsoft.Extensions.DependencyInjection.SwaggerGenServiceCollectionExtensions.CreateSchemaRegistryFactory(IServiceProvider serviceProvider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.FactoryService.Invoke(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ScopedCallSite.Invoke(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.SingletonCallSite.Invoke(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass12_0.b__0(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderExtensions.GetRequiredService[T](IServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.SwaggerGenServiceCollectionExtensions.CreateSwaggerProvider(IServiceProvider serviceProvider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.FactoryService.Invoke(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ScopedCallSite.Invoke(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.SingletonCallSite.Invoke(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass12_0.b__0(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
at Microsoft.AspNet.Builder.SwaggerGenBuilderExtensions.ThrowIfServiceNotRegistered(IServiceProvider applicationServices)
at Microsoft.AspNet.Builder.SwaggerGenBuilderExtensions.UseSwaggerGen(IApplicationBuilder app, String routeTemplate)
at %.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) in C:\Users..\Startup.cs:line 85

Use as library / document multiple APIs

Been looking into using Ahoy/SwaggerGen to document multiple APIs in an ASPNET5 application. My app has a frontend API and a backend API meant for different audiences, and their documentations should not be mixed. The APIs are exposed through urls like f.ex

  • /api/backend/v1/product/...
  • /api/frontend/v1/product/...

I wasnt able to get the desired results without some customizations: use the interesting bits of SwaggerGen to generate the SwaggerDocument in custom controllers, bypass the SwaggerMiddlewares altogether and use swagger-ui manually.

It requires modifying or adding a new ISwaggerProvider.GetSwagger2() method to better control whats included in the SwaggerDocument. In the code below, GetSwagger2() uses the whole basePath to evaluate which methods to include, rather that just the version part.

Would it be possible to allow something like this as standard?

Regards
Anders

    // MyController.cs
    [HttpGet("{version}/swagger.json")]
    public IActionResult Swagger(string version) {
        var info = new Info();
        info.Title = "My API";
        info.Description = "My API documentation";
        info.Version = version;

        var settings = new Newtonsoft.Json.JsonSerializerSettings() {
            ContractResolver = new SwaggerGenContractResolver(),
            NullValueHandling = NullValueHandling.Ignore
        };

        var response = SwaggerProvider.GetSwagger2(info, "http://localhost:49652", "api/backend/" + version);
        return Json(response, settings);
    }

...

    // SwaggerProvider.cs - also added in ISwaggerProvider.cs!
    public SwaggerDocument GetSwagger2(
        Info info,
        string host = null,
        string basePath = null,
        string[] schemes = null) {
        var schemaRegistry = _schemaRegistryFactory.Create();

        // the only change is here on the top to avoid using GetApiDescriptionsFor():
        var allDescriptions = _apiDescriptionsProvider.ApiDescriptionGroups.Items
            .SelectMany(group => group.Items)
            .Where(x => x.RelativePath.StartsWith(basePath));

        var paths = allDescriptions
            .Where(apiDesc => !(_options.IgnoreObsoleteActions && apiDesc.IsObsolete()))
            .OrderBy(_options.GroupNameSelector, _options.GroupNameComparer)
            .GroupBy(apiDesc => apiDesc.RelativePathSansQueryString())
            .ToDictionary(group => "/" + group.Key, group => CreatePathItem(group, schemaRegistry));

        var swaggerDoc = new SwaggerDocument {
            Info = info,
            Host = host,
            BasePath = basePath,
            Schemes = schemes,
            Paths = paths,
            Definitions = schemaRegistry.Definitions,
            SecurityDefinitions = _options.SecurityDefinitions
        };

        var filterContext = new DocumentFilterContext(
            _apiDescriptionsProvider.ApiDescriptionGroups,
            null);

        foreach (var filter in _options.DocumentFilters) {
            filter.Apply(swaggerDoc, filterContext);
        }

        return swaggerDoc;
    }

beta8: Swagger basePath validation error

First, thanks for getting the beta8 build out. I've gotten it integrated successfully, except for one glitch.

The Swagger UI loads but my Swagger JSON won't validate properly.

I get this error:

[{"level":"error","domain":"validation","keyword":"pattern","message":"ECMA 262 regex "^/" does not match input string ""","schema":{"loadingURI":"#","pointer":"/properties/basePath"},"instance":{"pointer":"/basePath"}}]

My guess is that it's from having a null basePath?

I'd actually prefer to have a basePath of /api/v1, and have the rest of the paths be relative.

Is this configurable via Swashbuckle?

"swagger": "2.0",
"info": {
    "version": "v1",
    "title": "API V1"
},
"basePath": "",
"paths": {
    "/api/v1/vendors/{vendorId}/applications": {

JsonConverterAttribute not respected

I am using a custom JsonConverter which is configured using an JsonConverterAttribute. It gets called and used in ASP.NET 5's controllers but Ahoy does not use it so the output shown in the model schema by Ahoy's GUI is wrong.

Steps to reproduce:
A. Add a produce attribute to a controller method to inform Ahoy of the response type.

[Produces(typeof(IResource<Employment>))]

B. Add a JsonConverterAttribute to the above IResource type

[JsonConverter(typeof(ResourceJsonConverter))]

The ResourceJsonConverter now gets called by ASP.NET 5 but not by Ahoy (bug)

Response Codes not interpreted from the XML

The node <response ... /> is not interpreted from the XML Comments file.

I think is a missing method to use and read Swashbuckle.Swagger.XmlComments.ApplyXmlActionComments.ResponseExpression.

Best regards,
Yann

Generate Swagger file from dnx console app

Hi,

Is it possible to generate a swagger file from a dnx console app? I'm looking into the possibility of adding a second command to our asp.net app to generate the file so that we can then generate a client for the api as part of our build process.

Thanks

Query string parameters missing

I created a new ASP.NET 5 project using Swashbuckle 6.0.0-rc1-final and configured with the following controller:

[Route("api/[controller]")]
public class SecurityController : Controller
{
[HttpPost]
[Route("Login")]
public void Login(string userName, string password)
{
}
}

Swagger renders the method correctly and provides inputs for the parameters but the Request URL sent from the UI doesnt include the parms. This same controller works correctly with a WebAPI 2.2 project.

Swagger-ui.js get error 500

I am working on a sample application, I have swagger running fine on windows using 1.0.0-beta7 coreclr x64, by running dnu web command. But using the same code running on Ubuntu 14.04 but run 'dnx kestrel', also same 1.0.0-beta7 coreclr x64, I am not able to have correct swagger ui rendered. To be specific: I got 500 for a static file:Swagger-ui.js

index.html 200 document Other 4.6 KB 200 ms
reset.css 304 stylesheet index.html:9 201 B 89 ms
screen.css 304 stylesheet index.html:10 201 B 90 ms
typography.css 304 stylesheet index.html:8 201 B 89 ms
jquery-1.8.0.min.js 304 script index.html:13 215 B 85 ms
jquery.slideto.min.js 304 script index.html:14 215 B 85 ms
jquery.wiggle.min.js 304 script index.html:15 215 B 86 ms
handlebars-2.0.0.js 304 script index.html:17 215 B 89 ms
underscore-min.js 304 script index.html:18 215 B 98 ms
swagger-ui.js 500 script index.html:20 0 B 193 ms
backbone-min.js 304 script index.html:19 215 B 98 ms
jquery.ba-bbq.min.js 304 script index.html:16 215 B 96 ms
marked.js 304 script index.html:22 215 B 97 ms
highlight.7.3.pack.js 304 script index.html:21 215 B 96 ms
swagger-oauth.js 304 script index.html:23 215 B 97 ms
print.css 304 stylesheet index.html:12 201 B 15 ms
logo_small.png 304 png jquery-1.8.0.min.js:2 202 B 4 ms
droid-sans-v6-latin-700.woff2 304 font jquery-1.8.0.min.js:2 215 B 4 ms
favicon-16x16.png 200 png Other 858 B 11 ms
favicon-32x32.png 304 png Other 202 B 3 ms

Cannot access ui or json

Hello,

I tried adding the package via nuget but I could not access the extension methods for Swagger

"Swashbuckle": "6.0.0-beta1"

So I decided to clone the repo locally the add it to my solution as a project and to my vNext project as a dependency. The solution built and the vNext website run. Unfortunately, I cannot access /swagger/ui neither can I access /swagger/v1/swagger.json. Here is my setup
Inside the ConfigureServices method

// Add swagger documentation
services.AddSwagger(s => {
    s.SwaggerGeneratorOptions(c => {
        s.SwaggerGeneratorOptions.Schemes = new[] { "http", "https" };
        s.SwaggerGeneratorOptions.SingleApiVersion(new Swashbuckle.Swagger.Info {
            Version = "v1",
            Title = "My vNext Api",
            Description = "some placeholder for description",
            TermsOfService = "some terms if need be"
    });

    s.SchemaGeneratorOptions.DescribeAllEnumsAsStrings = true;
});

Inside the Configure method

// Add Swagger Docs
app.UseSwagger();
app.UseSwaggerUi();

I put breakpoints to ensure that they initialized and yes they did. Any guidance?

See tags in XML comments not handled

Ahoy does not resolve a see tag in the XML comments correctly as shown in the example below. Instead of showing the reference endpoint it displayes the string "{X:XXX.XXX.XXX.Version}" inline in the generate HTML text

/// <summary>
///  Bla. bla. use the <see cref="Version"/> method instead.
/// </summary>

Bare bones installation guide?

Hey guys!

So I found out about Swagger a few days ago - but as I am in *.rc1-final of the MVC tooling it looks like Ahoy is my only real option for Swagger integration (outside of doing it by hand, of course).

I looked at the pull request with partial install instructions, but that is targeted as RC8, and I know there were some changes that mattered from there to rc1.

If we could get any sort of guidance, I will be happy to get it running and write a more significant bit of text on the process and contribute that back into the codebase.

Thanks for all your work in any case.

System.NullReferenceException in XmlCommentsModelFilter.ApplyPropertyComments

Just yesterday I've tried this nice little tool and unfortunately I've got a NRE.

the controller code looks like this:

public class Item
  {
    /// <summary>
    /// or that
    /// </summary>
    public int Id;
    /// <summary>
    /// or this
    /// </summary>
    public string Name;
  }

  /// <summary>
  /// Some summary
  /// </summary>
  /// 
  [Route("api/[Controller]")]
  [Produces("application/json", "text/json")]
  public class ItemsController : Controller
  {
    /// <summary>
    /// Return all items
    /// </summary>
    public static List<Item> Items = new List<Item>
    {
      new Item { Id = 1, Name = "First Test Item" },
      new Item { Id = 2, Name = "Second Test Item" },
    };

    /// <summary>
    /// Get all items
    /// </summary>
    /// <remarks>This will return all items</remarks>
    /// <returns>RETURN</returns>
    [HttpGet]
    public IEnumerable<Item> Get()
    {
      return Items;
    }

    /// <summary>
    /// Get Item by Id
    /// </summary>
    /// <param name="id">A var</param>
    /// <param name="dummy">just a dummy var</param>
    /// <returns>RETURN</returns>
    [HttpGet("itemId")]
    public Item Get([FromQuery]int id, int dummy)
    {
      return Items.FirstOrDefault(item => item.Id == id);
    }
  }

Using xml comments this will result in a Null reference Exception in XmlCommentsModelFilter.ApplyPropertyComments @ line 43
The problem is that memberInfo is null.

The problem seems to be with this part of the code above:

public class Item
  {
    /// <summary>
    /// or that
    /// </summary>
    public int Id;
    /// <summary>
    /// or this
    /// </summary>
    public string Name;
  }

I fixed it by adding

if (memberInfo == null) return;

But I don't know if this is actually the proper way in doing it.

By the way: Will there be also a .Net4.5.1 version of Swashbuckle? :)
We plan to use it in MediaPortal2 and this is based on .Net4.5.1.

RC1 publish

Any chance of getting an RC1-final published to nuget? Looks like the code is all there.

Invalid swagger parameters generation

if we have some param in the route, but we don't catch this parameter in action's parameters

    [Route("api/users/{userId}/[controller]")]
    public class OrdersController : Controller
    {
        [HttpGet]
        public async Task<IActionResult> Get(int orderId)
        {
            //// action code
        }
    }

we will get wrong swagger data for this parameter (without type)

parameters: [
    {
        name: "orderId",
        in: "path",
        required: true,
        type: "integer",
        format: "int32"
    },
    {
        name: "userId",
        in: "path",
        required: true
    }
],

and swagger-ui 2.1.0 and greater couldn't render this file

IParameter cannot be deserialized

Currently if there are any method parameters, the following:

Newtonsoft.Json.JsonConvert.DeserializeObject<SwaggerDocument>(swaggerString);

Fails with

An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll but was not handled in user code. Additional information: Could not create an instance of type Swashbuckle.Swagger.IParameter. Type is an interface or abstract class and cannot be instantiated.`.

I worked around this by adding type tags in the constructor of SwaggerDocsMiddleware:

        _swaggerSerializer = new JsonSerializer
        {
            NullValueHandling = NullValueHandling.Ignore,
            ContractResolver = new SwaggerDocsContractResolver(),
            TypeNameHandling = TypeNameHandling.Objects // add type tags
        };

and then the following works:

JsonConvert.DeserializeObject<SwaggerDocument>(swaggerString, new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Objects});

Seems like a bug to me, or perhaps there's an obvious workaround I missed?

Example of setting service method response type?

This may be a silly question reflecting a service with odd code.

I have a simple service that returns an object using Aspnet 5 rc1. Method declaration looks like:

public ActionResult GetByProductId(int productId) => new ObjectResult(_productInfoRepository.DescribeProductByProductId(productId));

Where the respository returns a Product object.

Understandably - swagger isn't reflecting that response type. Is there an annotation I should be using to mark up the method to reflect the actual response type the client will be seeing?

Thanks

UI page not rendering

Not sure if I'm doing anything wrong. I have referenced and done the whole setup in the startup class as follows:

 public void ConfigureServices(IServiceCollection services)
    {
         services.AddMvc();
       services.AddSwagger();

  }

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
app.UseMvc();
app.UseIdentity();
app.UseSwagger();
app.UseSwaggerUi();
}
when I launch and navigate to the doc url e.g. http://localhost:44023/swagger/ui/index.html
there is no doc end-point listed. It basically fails to render the ui. I checked the network calls and I can see the json results coming back from the server but no ui is rendered.

I do see that there is a javascript error after the response comes back in the swagger-ui.min.js: "Invalid string length"

swaggerjs
swagger-json
swaggerui

No apparent way to add Operation Response Headers

I tried to create a custom attribute (ResponseHeaderAttribute) which I look for with an OperationFilter and then add a new Header object to the operation.Responses.Headers collection (for the appropriate response), however I find there is no "name" attribute on the Header class and the Headers collection is just a List

- I had expected a Dictionary<string, Header> and assumed that the Header "name" would be the key, but it appears not. How should I add, for example an ETag header to the 201 Response from a POST?

Regards,

Michael R. Gilbert

Disabling the Validator

How do you disable the validator in this new API? You could do this in the old API:

config.EnableSwagger().EnableSwaggerUi(c => c.DisableValidator());

Inject a custom stylesheet?

Is there a way to inject a custom stylesheet like in Swashbuckle for WebAPI?

.EnableSwaggerUi(x =>
            {
                x.InjectStylesheet(typeof(AppHost).Assembly, "MyProject.Api.Resources.Swagger.UiCustomization.css");
            });

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.