Skip to content

AspNetCoreOpenApiDocumentGenerator

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

This generator uses the ASP.NET Core API Explorer service to generate specs and will eventually supersede the reflection based generator WebApiOpenApiDocumentGenerator. It is recommended to use this generator for new projects and also start migrating existing 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.

Additionally supported 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 ProducesResponseType 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 ProducesDefaultResponseType 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).

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;
    }
}

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