Web API controller methods can take in a CancellationToken parameter to provide cancellation support.
Swagger currently documents this as a REST parameter, but is an internal Web API thing and shouldn't be documented.
Swashbuckle is built on top of WebApis' own metadata layer - ApiExplorer. Despite being an internal WebApi thing, it is still being reported as an API parameter by ApiExplorer so really that's where the issue lies.
To keep complexity down and reduce the potential for compatibility issues, I like to rely on the underlying framework as much as possible so would opt against supporting a workaround out-of-the-box.
However, you can easily workaround this yourself by creating a custom IOperationFilter (see readme) that removes the cancellationToken param from the provided operation.
Anybody has an example on how to filter CancellationToken type out?
@mchambaud: Give this a try.
public class CancellationTokenOperationFilter : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var excludedParameters = apiDescription.ParameterDescriptions
.Where(p => p.ParameterDescriptor.ParameterType == typeof (CancellationToken))
.Select(p => operation.parameters.FirstOrDefault(operationParam => operationParam.name == p.Name))
.ToArray();
foreach (var parameter in excludedParameters)
operation.parameters.Remove(parameter);
}
}
Thanks @gisenberg
Thanks for this. I had to this now:
public class CancellationTokenOperationFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
var apiDescription = context.ApiDescription;
var excludedParameters = apiDescription.ParameterDescriptions
.Where(p => p.ModelMetadata.ContainerType == typeof(CancellationToken) || p.ModelMetadata.ContainerType == typeof(WaitHandle) || p.ModelMetadata.ContainerType == typeof(SafeWaitHandle))
.Select(p => operation.Parameters.FirstOrDefault(operationParam => operationParam.Name == p.Name))
.ToArray();
foreach (var parameter in excludedParameters)
operation.Parameters.Remove(parameter);
}
}
For a clean way (while only abusing c# attributes) to ignore any parameter, I've been using this:
SwaggerIgnoreAttribute.cs
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
public sealed class SwaggerIgnoreAttribute : Attribute
{
public SwaggerIgnoreAttribute()
{
}
}
CustomOperationFilter.cs
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
// Remove hidden parameters from the documentation
if (operation.parameters != null)
{
foreach (var parameter in apiDescription.ActionDescriptor.GetParameters())
{
if (parameter.GetCustomAttributes<SwaggerIgnoreAttribute>().Any())
{
operation.parameters.Remove(operation.parameters.First(x => string.Equals(parameter.ParameterName, x.name)));
}
}
}
}
ValuesController.cs
public class ValuesController : ApiController
{
...
// GET api/values/5
public async Task<string> GetAsync([SwaggerIgnore] CancellationToken ct, int id)
{
return await Task.Run(() => { return "value";});
}
}
It would be nice if this was baked into Swashbuckle IMO :). Would the package owners be interested?
Most helpful comment
Thanks for this. I had to this now: