I am using Swashbuckle (swagger for C#) with my Web API. I have several GET End-Points that return lists and I allow the user to add a perpage and page params into the QueryString
Example: http://myapi.com/endpoint/?page=5&perpage=10
I see that swagger does support parameter in 'query' but how do I get Swashbuckle to do it?
I mention in one of the comments that I solved my issue by creating a custom attribute to allow me to do what I needed. Below is the code for my solution:
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
public class SwaggerParameterAttribute : Attribute
{
public SwaggerParameterAttribute(string name, string description)
{
Name = name;
Description = description;
}
public string Name { get; private set; }
public Type DataType { get; set; }
public string ParameterType { get; set; }
public string Description { get; private set; }
public bool Required { get; set; } = false;
}
Register the Attribute with the Swagger Config:
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.OperationFilter<SwaggerParametersAttributeHandler>();
});
Then add this attribute to your methods:
[SwaggerParameter("page", "Page number to display", DataType = typeof(Int32), ParameterType = ParameterType.inQuery)]
[SwaggerParameter("perpage","Items to display per page", DataType = typeof(Int32), ParameterType = ParameterType.inQuery)]
You can achieve that quite easily. Suppose you have an ItemsController
with an action like this:
[Route("/api/items/{id}")]
public IHttpActionResult Get(int id, int? page = null, int? perpage = null)
{
// some relevant code
return Ok();
}
Swashbuckle will generate this specification (only showing relevant part):
"paths":{
"/api/items/{id}":{
"get":{
"parameters":[
{
"name":"id",
"in":"path",
"required":true,
"type":"integer",
"format":"int32"
},
{
"name":"page",
"in":"query",
"required":false,
"type":"integer",
"format":"int32"
},
{
"name":"limit",
"in":"query",
"required":false,
"type":"integer",
"format":"int32"
}
]
}
}
When you want page
and perpage
to be required, just make the parameters not nullable.
Here is a summary of the steps required (ASP.Net Core 2.1, Swashbuckle.AspNetCore v4.0.1) for the Attribute method. I needed a parameter starting with "$" so optional parameters were not an option!
SwaggerParameterAttribute.cs
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
public class SwaggerParameterAttribute : Attribute
{
public SwaggerParameterAttribute(string name, string description)
{
Name = name;
Description = description;
}
public string Name { get; private set; }
public string DataType { get; set; }
public string ParameterType { get; set; }
public string Description { get; private set; }
public bool Required { get; set; } = false;
}
SwaggerParameterAttributeFilter.cs
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Linq;
public class SwaggerParameterAttributeFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
var attributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
.Union(context.MethodInfo.GetCustomAttributes(true))
.OfType<SwaggerParameterAttribute>();
foreach (var attribute in attributes)
operation.Parameters.Add(new NonBodyParameter
{
Name = attribute.Name,
Description = attribute.Description,
In = attribute.ParameterType,
Required = attribute.Required,
Type = attribute.DataType
});
}
}
add this in Startup.ConfigureServices
using Swashbuckle.AspNetCore.Swagger;
services.AddSwaggerGen(c =>
{
c.OperationFilter<SwaggerParameterAttributeFilter>();
c.SwaggerDoc("v1.0", new Info { Title = "My API", Version = "v1.0" });
});
and use like this:
[SwaggerParameter("$top", "Odata Top parameter", DataType = "integer", ParameterType ="query")]
DataTypes can be: integer, string, boolean
ParameterTypes: can be path, body, query
There's some comments here regarding missing information on the SwaggerParametersAttributeHandler. It is an operation filter to help you determine what to do to your attributes.
Here's an example handler I used that allows me to override nullable parameters' required fields using the SwaggerParameterAttribute.
public class RequiredParameterOverrideOperationFilter : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
// Get all SwaggerParameterAttributes on the method
var attributes = apiDescription.ActionDescriptor.GetCustomAttributes<SwaggerParameterAttribute>();
if (operation.parameters == null)
{
operation.parameters = new List<Parameter>();
}
// For each attribute found, find the operation parameter (this is where Swagger looks to generate the Swagger doc)
// Override the required fields based on the attribute's required field
foreach (var attribute in attributes)
{
var referencingOperationParameter = operation.parameters.FirstOrDefault(p => p.name == attribute.Name);
if (referencingOperationParameter != null)
{
referencingOperationParameter.required = attribute.Required;
}
}
}
}
来源:https://stackoverflow.com/questions/35828328/adding-query-string-params-to-my-swagger-specs