有没有办法让 Swashbuckle 将 OData 参数添加到 Web API 2 IQueryable<T> 端点?
Is there a way to get Swashbuckle to add OData parameters to Web API 2 IQueryable<T> endpoint?
我有一个支持 OData 查询的 ASP.Net Web API 2 端点。是这样的:
[HttpGet, Route("")]
public IQueryable<Thing> Get()
{
return _thingsRepository.Query();
}
OData $filter 参数等非常有用。我只希望它们能像实际 OData 控制器一样出现在 Swagger 中。
我正在使用 Swashbuckle.OData ...但我真的不确定在这种情况下它是否能给我带来任何好处。
事实证明,使用 IOperationFilter
使用 SwashBuckle 向 Swagger 添加您想要的任何参数非常容易。您可以使用 c.OperationFilter<ODataParametersSwaggerDefinition>();
在您的 Swagger 配置中添加它。我创建了一个向 API:
中的所有 IQueryable 端点添加一些 OData 参数的方法
/// <summary>
/// Add the supported odata parameters for IQueryable endpoints.
/// </summary>
public class ODataParametersSwaggerDefinition : IOperationFilter
{
private static readonly Type QueryableType = typeof(IQueryable);
/// <summary>
/// Apply the filter to the operation.
/// </summary>
/// <param name="operation">The API operation to check.</param>
/// <param name="schemaRegistry">The swagger schema registry.</param>
/// <param name="apiDescription">The description of the api method.</param>
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var responseType = apiDescription.ResponseType();
if (responseType.GetInterfaces().Any(i => i == QueryableType))
{
operation.parameters.Add(new Parameter
{
name = "$filter",
description = "Filter the results using OData syntax.",
required = false,
type = "string",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$orderby",
description = "Order the results using OData syntax.",
required = false,
type = "string",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$skip",
description = "The number of results to skip.",
required = false,
type = "integer",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$top",
description = "The number of results to return.",
required = false,
type = "integer",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$count",
description = "Return the total count.",
required = false,
type = "boolean",
@in = "query"
});
}
}
}
直接窃取已接受的答案,但要进行额外的空值检查。
这不会触及您现有的 OData 可查询端点,这些端点可能已经定义了 parameters
,但只会增强您的可查询 ApiController
端点。
已更新 AspNetCore / Net 5、Net 6 答案
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
using System.Linq;
namespace My.Corporation.Api
{
/// <summary>
/// Help your swagger show OData query options with example pre-fills
/// </summary>
public class ODataParametersSwaggerDefinition : IOperationFilter
{
private static readonly Type QueryableType = typeof(IQueryable);
private static readonly OpenApiSchema stringSchema = new OpenApiSchema { Type = "string" };
private static readonly OpenApiSchema intSchema = new OpenApiSchema { Type = "integer" };
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var hasNoParams = (operation.Parameters == null || operation.Parameters.Count == 0);
var isQueryable = context.MethodInfo.ReturnType.GetInterfaces().Any(i => i == QueryableType);
if (hasNoParams && isQueryable)
{
operation.Parameters = new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter
{
Name = "$filter",
Description = "Filter the results using OData syntax.",
Example = OpenApiAnyFactory.CreateFor(stringSchema,"ProductName eq 'YOGURT'"),
Required = false,
In = ParameterLocation.Query,
Schema = stringSchema
});
operation.Parameters.Add(new OpenApiParameter
{
Name = "$select",
Description = "Trim the fields returned using OData syntax",
Example = OpenApiAnyFactory.CreateFor(stringSchema, "Id,ProductName"),
Required = false,
In = ParameterLocation.Query,
Schema = new OpenApiSchema { Type = "string" }
});
operation.Parameters.Add(new OpenApiParameter
{
Name = "$orderby",
Description = "Order the results using OData syntax.",
Example = OpenApiAnyFactory.CreateFor(stringSchema, "Price,ProductName ASC"),
Required = false,
In = ParameterLocation.Query,
Schema = new OpenApiSchema { Type = "string" }
});
operation.Parameters.Add(new OpenApiParameter
{
Name = "$skip",
Description = "The number of results to skip.",
Example = OpenApiAnyFactory.CreateFor(intSchema, 100),
Required = false,
In = ParameterLocation.Query,
Schema = intSchema
});
operation.Parameters.Add(new OpenApiParameter
{
Name = "$top",
Description = "The number of results to return.",
Example = OpenApiAnyFactory.CreateFor(intSchema, 50),
Required = false,
In = ParameterLocation.Query,
Schema = intSchema
});
}
}
}
}
原始 WebAPI 2 答案
/// <summary>
/// Adds the supported odata parameters for IQueryable endpoints
/// ONLY if no parameters are defined already.
/// </summary>
public class ODataParametersSwaggerDefinition : IOperationFilter
{
private static readonly Type QueryableType = typeof(IQueryable);
/// <summary>
/// Apply the filter to the operation.
/// </summary>
/// <param name="operation">The API operation to check.</param>
/// <param name="schemaRegistry">The swagger schema registry.</param>
/// <param name="apiDescription">The description of the api method.</param>
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var responseType = apiDescription.ResponseType();
if (responseType.GetInterfaces().Any(i => i == QueryableType))
{
if (operation.parameters == null)
{
operation.parameters = new List<Parameter>();
operation.parameters.Add(new Parameter
{
name = "$filter",
description = "Filter the results using OData syntax.",
required = false,
type = "string",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$orderby",
description = "Order the results using OData syntax.",
required = false,
type = "string",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$skip",
description = "The number of results to skip.",
required = false,
type = "integer",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$top",
description = "The number of results to return.",
required = false,
type = "integer",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$count",
description = "Return the total count.",
required = false,
type = "boolean",
@in = "query"
});
}
}
}
}
使用 Swashbuckle.AspNetCore v. 6.2.3 看起来像这样:
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (context.MethodInfo.ReturnType.GetInterfaces().Any(i => i == typeof(IQueryable)))
{
operation.Parameters.Add(new OpenApiParameter()
{
Name = "$filter",
Description = "My $filter filter",
Required = false,
In = ParameterLocation.Query,
});
operation.Parameters.Add(new OpenApiParameter()
{
Name = "$top",
Description = "My $top filter",
Required = false,
In = ParameterLocation.Query,
});
operation.Parameters.Add(new OpenApiParameter()
{
Name = "$expand",
Description = "My $top filter",
Required = false,
In = ParameterLocation.Query,
});
}
}
我有一个支持 OData 查询的 ASP.Net Web API 2 端点。是这样的:
[HttpGet, Route("")]
public IQueryable<Thing> Get()
{
return _thingsRepository.Query();
}
OData $filter 参数等非常有用。我只希望它们能像实际 OData 控制器一样出现在 Swagger 中。
我正在使用 Swashbuckle.OData ...但我真的不确定在这种情况下它是否能给我带来任何好处。
事实证明,使用 IOperationFilter
使用 SwashBuckle 向 Swagger 添加您想要的任何参数非常容易。您可以使用 c.OperationFilter<ODataParametersSwaggerDefinition>();
在您的 Swagger 配置中添加它。我创建了一个向 API:
/// <summary>
/// Add the supported odata parameters for IQueryable endpoints.
/// </summary>
public class ODataParametersSwaggerDefinition : IOperationFilter
{
private static readonly Type QueryableType = typeof(IQueryable);
/// <summary>
/// Apply the filter to the operation.
/// </summary>
/// <param name="operation">The API operation to check.</param>
/// <param name="schemaRegistry">The swagger schema registry.</param>
/// <param name="apiDescription">The description of the api method.</param>
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var responseType = apiDescription.ResponseType();
if (responseType.GetInterfaces().Any(i => i == QueryableType))
{
operation.parameters.Add(new Parameter
{
name = "$filter",
description = "Filter the results using OData syntax.",
required = false,
type = "string",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$orderby",
description = "Order the results using OData syntax.",
required = false,
type = "string",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$skip",
description = "The number of results to skip.",
required = false,
type = "integer",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$top",
description = "The number of results to return.",
required = false,
type = "integer",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$count",
description = "Return the total count.",
required = false,
type = "boolean",
@in = "query"
});
}
}
}
直接窃取已接受的答案,但要进行额外的空值检查。
这不会触及您现有的 OData 可查询端点,这些端点可能已经定义了 parameters
,但只会增强您的可查询 ApiController
端点。
已更新 AspNetCore / Net 5、Net 6 答案
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
using System.Linq;
namespace My.Corporation.Api
{
/// <summary>
/// Help your swagger show OData query options with example pre-fills
/// </summary>
public class ODataParametersSwaggerDefinition : IOperationFilter
{
private static readonly Type QueryableType = typeof(IQueryable);
private static readonly OpenApiSchema stringSchema = new OpenApiSchema { Type = "string" };
private static readonly OpenApiSchema intSchema = new OpenApiSchema { Type = "integer" };
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var hasNoParams = (operation.Parameters == null || operation.Parameters.Count == 0);
var isQueryable = context.MethodInfo.ReturnType.GetInterfaces().Any(i => i == QueryableType);
if (hasNoParams && isQueryable)
{
operation.Parameters = new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter
{
Name = "$filter",
Description = "Filter the results using OData syntax.",
Example = OpenApiAnyFactory.CreateFor(stringSchema,"ProductName eq 'YOGURT'"),
Required = false,
In = ParameterLocation.Query,
Schema = stringSchema
});
operation.Parameters.Add(new OpenApiParameter
{
Name = "$select",
Description = "Trim the fields returned using OData syntax",
Example = OpenApiAnyFactory.CreateFor(stringSchema, "Id,ProductName"),
Required = false,
In = ParameterLocation.Query,
Schema = new OpenApiSchema { Type = "string" }
});
operation.Parameters.Add(new OpenApiParameter
{
Name = "$orderby",
Description = "Order the results using OData syntax.",
Example = OpenApiAnyFactory.CreateFor(stringSchema, "Price,ProductName ASC"),
Required = false,
In = ParameterLocation.Query,
Schema = new OpenApiSchema { Type = "string" }
});
operation.Parameters.Add(new OpenApiParameter
{
Name = "$skip",
Description = "The number of results to skip.",
Example = OpenApiAnyFactory.CreateFor(intSchema, 100),
Required = false,
In = ParameterLocation.Query,
Schema = intSchema
});
operation.Parameters.Add(new OpenApiParameter
{
Name = "$top",
Description = "The number of results to return.",
Example = OpenApiAnyFactory.CreateFor(intSchema, 50),
Required = false,
In = ParameterLocation.Query,
Schema = intSchema
});
}
}
}
}
原始 WebAPI 2 答案
/// <summary>
/// Adds the supported odata parameters for IQueryable endpoints
/// ONLY if no parameters are defined already.
/// </summary>
public class ODataParametersSwaggerDefinition : IOperationFilter
{
private static readonly Type QueryableType = typeof(IQueryable);
/// <summary>
/// Apply the filter to the operation.
/// </summary>
/// <param name="operation">The API operation to check.</param>
/// <param name="schemaRegistry">The swagger schema registry.</param>
/// <param name="apiDescription">The description of the api method.</param>
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var responseType = apiDescription.ResponseType();
if (responseType.GetInterfaces().Any(i => i == QueryableType))
{
if (operation.parameters == null)
{
operation.parameters = new List<Parameter>();
operation.parameters.Add(new Parameter
{
name = "$filter",
description = "Filter the results using OData syntax.",
required = false,
type = "string",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$orderby",
description = "Order the results using OData syntax.",
required = false,
type = "string",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$skip",
description = "The number of results to skip.",
required = false,
type = "integer",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$top",
description = "The number of results to return.",
required = false,
type = "integer",
@in = "query"
});
operation.parameters.Add(new Parameter
{
name = "$count",
description = "Return the total count.",
required = false,
type = "boolean",
@in = "query"
});
}
}
}
}
使用 Swashbuckle.AspNetCore v. 6.2.3 看起来像这样:
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (context.MethodInfo.ReturnType.GetInterfaces().Any(i => i == typeof(IQueryable)))
{
operation.Parameters.Add(new OpenApiParameter()
{
Name = "$filter",
Description = "My $filter filter",
Required = false,
In = ParameterLocation.Query,
});
operation.Parameters.Add(new OpenApiParameter()
{
Name = "$top",
Description = "My $top filter",
Required = false,
In = ParameterLocation.Query,
});
operation.Parameters.Add(new OpenApiParameter()
{
Name = "$expand",
Description = "My $top filter",
Required = false,
In = ParameterLocation.Query,
});
}
}