如何在Swashbuckle中更改POST和PUT所需的字段?

问题描述 投票:-1回答:1

我负责维护公司的API文档。我们的API是用ASP.NET编写的。我最近改用了Swashbuckle 5.6.0,它工作得很好。

我遇到的问题是:

我们将数据模型分为Post数据和Get数据,例如WebAccountGetData.csWebAccountPostData.cs。创建(POST)和更新(PUT)时可以使用Post数据。

Post数据类中的大多数(如果不是全部)字段都是可空的,当调用API方法时,存储的proc返回描述缺少/需要哪些字段的错误消息。 API不处理必填字段。

使用可空字段意味着Swashbuckle不会在文档中添加Required标志。但我们想根据所使用的Http方法(Post / Put)来显示是否需要字段。

API密钥是必需参数,因为它不可为空。

我知道我可以使用System.ComponentModel.DataAnnotations命名空间中的[Required]属性,但这会将POST和PUT方法应用于Required标志,这是我们不想要的。

理想情况下,我想使用自定义属性,我可以指定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;
}

有没有办法使用自定义IDocumentFilterIOperationFilterISchemaFilter将更改(如切换所需的标志)应用于模型字段的架构属性?或者在Swashbuckle中不可能引用模型上的属性?

c# asp.net-web-api swashbuckle redoc
1个回答
0
投票

我设法找到了解决方案!

我创建了一个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方法参数位于右侧:

enter image description here enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.