簡體   English   中英

如何在 Swashbuckle 中更改 POST 和 PUT 的必填字段?

[英]How to vary the required fields for POST and PUT in Swashbuckle?

我負責維護公司 API 文檔。 我們的 API 是用 ASP.NET 編寫的。 我最近改用了運行良好的 Swashbuckle 5.6.0。

我遇到的問題是這樣的:

我們將數據模型分為 Post 數據和 Get 數據,例如WebAccountGetData.csWebAccountPostData.cs Post 數據可以在創建 (POST) 和更新 (PUT) 時使用。

Post 數據類中的大多數(如果不是全部)字段都是可為空的,當調用 API 方法時,存儲過程會返回錯誤消息,描述缺少/需要哪些字段。 API 不處理必填字段。

使用可為空字段意味着 Swashbuckle 不會在文檔中添加必需標志。 但是我們想根據所使用的 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;
}

有沒有辦法使用自定義IDocumentFilterIOperationFilterISchemaFilter將更改(如切換所需標志)應用於模型字段的架構屬性? 或者在 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 方法參數在右側:

在此處輸入圖片說明 在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM