Skip to content

AspNetCoreOpenApiDocumentGenerator

Rico Suter edited this page Jun 7, 2019 · 22 revisions

This generator uses the ASP.NET Core API Explorer service to generate specs and will replaces the reflection based generator WebApiOpenApiDocumentGenerator. It is recommended to always use this generator for ASP.NET Core projects!

The AspNetCoreOpenApiDocumentGenerator class is used to generate a OpenAPI/Swagger specification from ASP.NET Core controllers using the API Explorer and is used by the AspNetCore Middleware or via CLI.

The generator internally uses the JsonSchemaGenerator class (NJsonSchema project) to generate the JSON Schemas of the request and response DTO types.

Important: If you run this generator via NSwag.MSBuild as part of your .csproj build (after build target), you need to set NoBuild to true to avoid endless build recursions...

Remarks: If you are using .NET Core >= v2.1, you may need to set the CompatibilityVersion.

OpenAPI related attributes

  • Package: NSwag.Annotations

OpenApiIgnoreAttribute()

Excludes a Web API method from the Swagger specification.

OpenApiOperationAttribute(operationId)

Defines a custom operation ID for a Web API action method.

OpenApiTagsAttribute(tags)

Defines the operation tags. See Specify the operation tags.

OpenApiExtensionDataAttribute()

Adds extension data to the document (when applied to a controller class), an operation or parameter.

SwaggerResponseAttribute(httpAction, type) (not recommended/deprecated, use ASP.NET Core's ProducesResponseTypeAttribute instead)

Defines the response type of a Web API action method and HTTP action. See Specify the response type of an action.

SwaggerDefaultResponseAttribute() (not recommended/deprecated, use ASP.NET Core's ProducesDefaultResponseTypeAttribute instead)

Adds the default response (HTTP 200/204) based on the return type of the operation method. This can be used in conjunction with the SwaggerResponseAttribute or another response defining attribute (ProducesResponseTypeAttribute, etc.). This is needed because if one of these attributes is available, you have to define all responses and the default response is not automatically added. If an HTTP 200/204 response is already defined then the attribute is ignored (useful if the attribute is defined on the controller or the base class).

  • Package: NJsonSchema

NotNullAttribute and CanBeNullAttribute

Can be defined on DTO properties (handled by NJsonSchema), operation parameters and the return type with:

[return: NotNull]
public string GetName()

The default behavior can be changed with the WebApiOpenApiDocumentGeneratorSettings.DefaultReferenceTypeNullHandling setting (default: Default = Use Nullable Reference Types or Null for reference types).

There are many more attributes to control DTO schema generation.

Specify the operation response type and description

In ASP.NET Core you should only use ASP.NET Core attributes and avoid SwaggerResponseAttributes and SwaggerDefaultResponseAttributes.

The response type and description can be defined with the ProducesResponseTypeAttribute and XML docs:

/// <summary>
/// Creates an order.
/// </summary>
/// <param name="order"></param>
/// <response code="201">Order created.</response>
/// <response code="400">Order invalid.</response>
[HttpPost]
[ProducesResponseType(typeof(int), 201)]
[ProducesResponseType(typeof(IDictionary<string, string>), 400)]
public IActionResult CreateOrder()
{
    return new CreatedResult("/orders/1", 1);
}

To define an operation without a response (i.e. HTTP 204 or 404), use the ProducesResponseType attribute and typeof(void):

If the response type cannot be determined, the type of generated response will be file (sample is Swagger 2.0):

"responses": {
	"200": {
		"schema": {
			"type": "file"
		}
	}
}

To force a file response, specify the response type with the ProducesResponseTypeAttribute:

[ProducesResponseType(typeof(IActionResult), 200)]
public IActionResult DownloadFile(string name)
{
    ....
}

Working with HTTP status codes and exceptions

We recommend to catch exceptions and return them with a custom HTTP status code.

[HttpPost]
[ProducesResponseType(typeof(int), 200)]
[ProducesResponseType(typeof(LocationNotFoundException), 500)]
public async Task<ActionResult> Create([FromBody]Person person)
{
    try
    {
        var location = await _geoService.FindLocationAsync(person.Location);
        person.LocationLatitude = location.Latitude;
        person.LocationLongitude = location.Longitude;
    }
    catch (LocationNotFoundException locationNotFoundException)
    {
        return StatusCode(500, locationNotFoundException);
    }

    await _dataContext.SaveChangesAsync();
    return Ok(person.Id);
}

In order to correctly serialize the custom exception, just add the JsonExceptionConverter from the NJsonSchema NuGet package (or use the JsonExceptionFilterAttribute:

[JsonConverter(typeof(JsonExceptionConverter))]
public class LocationNotFoundException : Exception
{
    [JsonProperty("location")]
    public string Location { get;  }

    public LocationNotFoundException(string location, Exception exception)
        : base("The location could not be found.", exception)
    {
        Location = location;
    }
}

Response nullability

By default responses in ASP.NET Core are nullable (i.e. you can return null in your operation). However because most people design their APIs to never return null the default in the spec generator is to make responses not nullable. You can change this behavior globally by changing the DefaultResponseReferenceTypeNullHandling setting to Null.

To specify the nullability of a specific response, use XML docs like this:

/// <response code="200" nullable="true">The order.</response>
[HttpPost]
[ProducesResponseType(typeof(Order), 200)]
public IActionResult GetOrder(int id)
{
    ...
}

For more information, have a look at this PR.

Specify the operation tags

With the OpenApiTagsAttribute you can specify the Swagger/OpenAPI tags for a Web API action method:

[OpenApiTags("foo", "bar")]
public void MyActionMethod() 
{
	...
}

If the attribute is not available, the controller name is added to the list of operation tags.

File uploads

An operation parameter is treated as form file upload if it is/inherits/implements one of the following types (or a collection of it):

  • IFormFile
  • HttpPostedFile
  • HttpPostedFileBase

You can also add the OpenApiFileAttribute to a parameter or a class (implemented in the NSwag.Annotations package):

public void MyOperation([OpenApiFile] MyClass myParameter)
{
    ...
}

Known issues