如何在 Swashbuckle 中更改 POST 和 PUT 的必填字段?
How to vary the required fields for POST and PUT in Swashbuckle?
我负责维护公司 API 文档。我们的API写成ASP.NET。我最近转而使用运行良好的 Swashbuckle 5.6.0。
我遇到的问题是:
我们将数据模型分为 Post 数据和获取数据,例如 WebAccountGetData.cs
和 WebAccountPostData.cs
。 Post数据可以在创建(POST)和更新(PUT)时使用。
Post 数据 类 中的大多数(如果不是全部)字段可以为空,当调用 API 方法时,存储的过程 returns 错误消息描述missing/required 是什么字段。 API 不处理必填字段。
使用可为 null 的字段意味着 Swashbuckle 不会向文档中添加 Required 标志。但是我们想根据使用的 Http 方法显示是否需要字段 (Post/Put)。
API 键是必需参数,因为它不可为空。
我知道我可以使用 System.ComponentModel.DataAnnotations 命名空间中的 [Required]
属性,但这会将 Required 标志应用于 POST 和 PUT 方法,我们不想。
理想情况下,我想使用自定义属性,我可以在其中指定 Post 或 Put 方法中是否需要某个字段。
public class ApiRequiredAttribute : Attribute
{
public bool RequiredInPost
{
get;
set;
} = false;
public bool RequiredInPut
{
get;
set;
} = false;
}
然后像这样使用它:
[ApiRequired(RequiredInPost = true)]
public int? ApprovalStatusId
{
get;
set;
}
有没有办法使用自定义 IDocumentFilter
、IOperationFilter
或 ISchemaFilter
将更改(如切换所需标志)应用于模型字段的架构属性?或者在 Swashbuckle 中无法引用模型上的属性?
我找到了解决办法!
我创建了一个 IOperationFilter
,它根据具有我的自定义 ApiRequired
属性的属性为 POST 和 PUT 方法创建新模式(参见原始问题)。
internal class ApplyRequiredAttributeFilter : IOperationFilter
{
public void Apply( Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription )
{
HttpParameterBinding[] parameterBindings = apiDescription.ActionDescriptor.ActionBinding.ParameterBindings;
foreach ( HttpParameterBinding binding in parameterBindings ) {
PropertyInfo[] properties = binding.Descriptor.ParameterType.GetProperties();
// If the type is not an object and has no properties, ignore it.
if ( properties.Length == 0 ) {
continue;
}
Parameter modelParamater = operation.parameters.Last();
if ( modelParamater == null ) {
continue;
}
string schemaPath = modelParamater.schema?.@ref;
string schemaName = schemaPath?.Split( '/' ).Last();
if ( schemaName == null ) {
continue;
}
Schema oldSchema = schemaRegistry.Definitions[ schemaName ];
// Copy the existing schema.
Schema newSchema = new Schema
{
description = oldSchema.description,
properties = new Dictionary<string, Schema>( oldSchema.properties ),
required = oldSchema.required != null ? new List<string>( oldSchema.required ) : new List<string>(),
@type = oldSchema.type,
vendorExtensions = new Dictionary<string, object>( oldSchema.vendorExtensions )
};
// Find model properties with the custom attribute.
foreach ( PropertyInfo property in properties ) {
ApiRequiredAttribute attribute = property.GetCustomAttribute<ApiRequiredAttribute>();
if ( attribute != null ) {
// If the model property is required in POST/PUT and current HTTP method is POST/PUT
// Add the property to the new schema's required flags.
if ( attribute.RequiredInPut && apiDescription.HttpMethod.Method.Equals( "PUT" ) ||
attribute.RequiredInPost && apiDescription.HttpMethod.Method.Equals( "POST" ) ) {
newSchema.required.Add( property.Name );
string newSchemaName = $"{schemaName}:{apiDescription.HttpMethod.Method}";
if ( !schemaRegistry.Definitions.ContainsKey( newSchemaName ) ) {
schemaRegistry.Definitions.Add( newSchemaName, newSchema );
}
// Change the current model schema reference to the new schema with the addition required flags.
modelParamater.schema.@ref = $"{schemaPath}:{apiDescription.HttpMethod.Method}";
}
}
}
}
}
}
然后我将过滤器添加到我的 EnableSwagger 调用中。
GlobalConfiguration.Configuration
.EnableSwagger("docs/swagger/", c =>
{
// Other initialization code...
c.OperationFilter<ApplyRequiredAttributeFilter>();
});
属性是这样使用的:
[ApiRequired( RequiredInPost = true, RequiredInPut = true)]
public bool? Active
{
get;
set;
}
[ApiRequired( RequiredInPost = true )]
public string UserName
{
get;
set;
}
最后,在文档中,所需的标志如下所示。 POST 方法参数在左边,PUT 方法参数在右边:
我负责维护公司 API 文档。我们的API写成ASP.NET。我最近转而使用运行良好的 Swashbuckle 5.6.0。
我遇到的问题是:
我们将数据模型分为 Post 数据和获取数据,例如 WebAccountGetData.cs
和 WebAccountPostData.cs
。 Post数据可以在创建(POST)和更新(PUT)时使用。
Post 数据 类 中的大多数(如果不是全部)字段可以为空,当调用 API 方法时,存储的过程 returns 错误消息描述missing/required 是什么字段。 API 不处理必填字段。
使用可为 null 的字段意味着 Swashbuckle 不会向文档中添加 Required 标志。但是我们想根据使用的 Http 方法显示是否需要字段 (Post/Put)。
API 键是必需参数,因为它不可为空。
我知道我可以使用 System.ComponentModel.DataAnnotations 命名空间中的 [Required]
属性,但这会将 Required 标志应用于 POST 和 PUT 方法,我们不想。
理想情况下,我想使用自定义属性,我可以在其中指定 Post 或 Put 方法中是否需要某个字段。
public class ApiRequiredAttribute : Attribute
{
public bool RequiredInPost
{
get;
set;
} = false;
public bool RequiredInPut
{
get;
set;
} = false;
}
然后像这样使用它:
[ApiRequired(RequiredInPost = true)]
public int? ApprovalStatusId
{
get;
set;
}
有没有办法使用自定义 IDocumentFilter
、IOperationFilter
或 ISchemaFilter
将更改(如切换所需标志)应用于模型字段的架构属性?或者在 Swashbuckle 中无法引用模型上的属性?
我找到了解决办法!
我创建了一个 IOperationFilter
,它根据具有我的自定义 ApiRequired
属性的属性为 POST 和 PUT 方法创建新模式(参见原始问题)。
internal class ApplyRequiredAttributeFilter : IOperationFilter
{
public void Apply( Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription )
{
HttpParameterBinding[] parameterBindings = apiDescription.ActionDescriptor.ActionBinding.ParameterBindings;
foreach ( HttpParameterBinding binding in parameterBindings ) {
PropertyInfo[] properties = binding.Descriptor.ParameterType.GetProperties();
// If the type is not an object and has no properties, ignore it.
if ( properties.Length == 0 ) {
continue;
}
Parameter modelParamater = operation.parameters.Last();
if ( modelParamater == null ) {
continue;
}
string schemaPath = modelParamater.schema?.@ref;
string schemaName = schemaPath?.Split( '/' ).Last();
if ( schemaName == null ) {
continue;
}
Schema oldSchema = schemaRegistry.Definitions[ schemaName ];
// Copy the existing schema.
Schema newSchema = new Schema
{
description = oldSchema.description,
properties = new Dictionary<string, Schema>( oldSchema.properties ),
required = oldSchema.required != null ? new List<string>( oldSchema.required ) : new List<string>(),
@type = oldSchema.type,
vendorExtensions = new Dictionary<string, object>( oldSchema.vendorExtensions )
};
// Find model properties with the custom attribute.
foreach ( PropertyInfo property in properties ) {
ApiRequiredAttribute attribute = property.GetCustomAttribute<ApiRequiredAttribute>();
if ( attribute != null ) {
// If the model property is required in POST/PUT and current HTTP method is POST/PUT
// Add the property to the new schema's required flags.
if ( attribute.RequiredInPut && apiDescription.HttpMethod.Method.Equals( "PUT" ) ||
attribute.RequiredInPost && apiDescription.HttpMethod.Method.Equals( "POST" ) ) {
newSchema.required.Add( property.Name );
string newSchemaName = $"{schemaName}:{apiDescription.HttpMethod.Method}";
if ( !schemaRegistry.Definitions.ContainsKey( newSchemaName ) ) {
schemaRegistry.Definitions.Add( newSchemaName, newSchema );
}
// Change the current model schema reference to the new schema with the addition required flags.
modelParamater.schema.@ref = $"{schemaPath}:{apiDescription.HttpMethod.Method}";
}
}
}
}
}
}
然后我将过滤器添加到我的 EnableSwagger 调用中。
GlobalConfiguration.Configuration
.EnableSwagger("docs/swagger/", c =>
{
// Other initialization code...
c.OperationFilter<ApplyRequiredAttributeFilter>();
});
属性是这样使用的:
[ApiRequired( RequiredInPost = true, RequiredInPut = true)]
public bool? Active
{
get;
set;
}
[ApiRequired( RequiredInPost = true )]
public string UserName
{
get;
set;
}
最后,在文档中,所需的标志如下所示。 POST 方法参数在左边,PUT 方法参数在右边: