简体   繁体   English

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

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

I'm responsible for maintaining the company API documentation.我负责维护公司 API 文档。 Our API is written ASP.NET.我们的 API 是用 ASP.NET 编写的。 I recently switched to using Swashbuckle 5.6.0 which is working nicely.我最近改用了运行良好的 Swashbuckle 5.6.0。

The issue I've come accross is this:我遇到的问题是这样的:

We separate our data models into Post data and Get data, for example WebAccountGetData.cs and WebAccountPostData.cs .我们将数据模型分为 Post 数据和 Get 数据,例如WebAccountGetData.csWebAccountPostData.cs The Post data can be used when creating (POST) and updating (PUT). Post 数据可以在创建 (POST) 和更新 (PUT) 时使用。

Most, if not all, fields in the Post data classes are nullable, when an API method is called, the stored proc returns error messages describing what fields are missing/required. Post 数据类中的大多数(如果不是全部)字段都是可为空的,当调用 API 方法时,存储过程会返回错误消息,描述缺少/需要哪些字段。 The API doesn't handle required fields. API 不处理必填字段。

Using nullable fields means Swashbuckle will not add a Required flag to the documentation.使用可为空字段意味着 Swashbuckle 不会在文档中添加必需标志。 But we would like to show whether a field is required or not, based on the Http method used (Post/Put).但是我们想根据所使用的 Http 方法 (Post/Put) 显示是否需要某个字段。

必要的例子
The API Key is a required parameter as it is not nullable. API 密钥是必需参数,因为它不可为空。

I'm aware that I can use the [Required] attribute from the System.ComponentModel.DataAnnotations namespace, but this will apply the Required flag to both the POST and PUT methods, which we do not want.我知道我可以使用 System.ComponentModel.DataAnnotations 命名空间中的[Required]属性,但这会将 Required 标志应用于我们不想要的 POST 和 PUT 方法。

Idealy, I'd like to use a custom Attribute where I can specify whether a field is required in the Post or Put method.理想情况下,我想使用自定义属性,我可以在其中指定 Post 或 Put 方法中是否需要某个字段。

public class ApiRequiredAttribute : Attribute
{
  public bool RequiredInPost
  {
    get;
    set;
  } = false;

  public bool RequiredInPut
  {
    get;
    set;
  } = false;
}

And then use it like so:然后像这样使用它:

[ApiRequired(RequiredInPost = true)]
public int? ApprovalStatusId
{
  get;
  set;
}

Is there a way to use a custom IDocumentFilter , IOperationFilter or ISchemaFilter to apply changes (like toggling the required flag) to the schema properties of a model field?有没有办法使用自定义IDocumentFilterIOperationFilterISchemaFilter将更改(如切换所需标志)应用于模型字段的架构属性? Or is it not possible in Swashbuckle to reference Attributes on a model?或者在 Swashbuckle 中无法引用模型上的属性?

I've managed to find a solution!我设法找到了解决方案!

I created an IOperationFilter that creates new schemas for POST and PUT methods, based on properties with my custom ApiRequired attribute (see original question).我创建了一个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}";
          }
        }
      }
    }
  }
}

I then add the filter to my EnableSwagger call.然后我将过滤器添加到我的 EnableSwagger 调用中。

GlobalConfiguration.Configuration
                   .EnableSwagger("docs/swagger/", c =>
                                    {
                                      // Other initialization code... 
                                      c.OperationFilter<ApplyRequiredAttributeFilter>();
                                    });

The attributes are used like so:属性的使用方式如下:

[ApiRequired( RequiredInPost = true, RequiredInPut = true)]
public bool? Active
{
  get;
  set;
}

[ApiRequired( RequiredInPost = true )]
public string UserName
{
  get;
  set;
}

Finally, on the docs, the required flags look like this.最后,在文档上,所需的标志如下所示。 The POST method parameters are on the left while the PUT method paramaters are on the right: POST 方法参数在左侧,而 PUT 方法参数在右侧:

在此处输入图片说明 在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM