问题
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)]
回答1:
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.
回答2:
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
回答3:
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