首页 > 解决方案 > 在 swagger 上渲染时忽略 [FromForm] 数据

问题描述

我正在使用 .Net 5 Web API 并且我正在使用Swashbuckle,当我[JsonIgnore]在我的模型上使用它时,它可以很好地渲染我的 JSON

模型 :

    public partial class ApplicationDocument : BaseModel
    {
        public int id { get; set; }
        public int document_id { get; set; }
        public int application_id { get; set; }
        [NotMapped]
        public string name { get; set; }
        [NotMapped]
        public string documentUrl { get; set; }
        [JsonIgnore]
        public virtual Application application { get; set; }
        [JsonIgnore]
        public virtual Document document { get; set; }
    }

JSON

{
  "applicationDocument": {
    "dateCreated": "2021-05-17T13:08:08.934Z",
    "dateModified": "2021-05-17T13:08:08.934Z",
    "createdBy": "string",
    "modifiedBy": "string",
    "isActive": true,
    "isDeleted": true,
    "id": 0,
    "document_id": 0,
    "application_id": 0,
    "name": "string",
    "documentUrl": "string"
  },
  "fileDocument": "string"
}

问题是当我在[FromForm]控制器中使用该属性时,[JsonIgnore] 对我不起作用,它渲染了每个字段,甚至是导航字段

控制器

        [HttpPost]
        [Route("[controller]/AddApplicationDocument")]
        public BaseResponse AddApplicationDocument([FromForm] ApplicationDocumentViewModel ApplicationDocumentViewModel)
        {
            return _ApplicationDocument.AddApplicationDocument(ApplicationDocumentViewModel);
        }

像这样显示

标签: c#asp.net-coreasp.net-web-apiswagger.net-5

解决方案


我有一个想法给你,我希望你能解决你的问题。

首先,创建此属性:

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class SwaggerIgnoreAttribute : Attribute
{
}

然后,为 swagger 选项创建一个 OperationFilter 和一个 SchemaFilter :

public class IgnorePropertyFilter : IOperationFilter
    {
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            if (context.ApiDescription == null || operation.Parameters == null)
                return;

            if (!context.ApiDescription.ParameterDescriptions.Any())
                return;


            var excludedProperties = context.ApiDescription.ParameterDescriptions.Where(p =>
                p.Source.Equals(BindingSource.Form));

            if (excludedProperties.Any())
            {

                foreach (var excludedPropertie in excludedProperties)
                {
                    foreach (var customAttribute in excludedPropertie.CustomAttributes())
                    {
                        if (customAttribute.GetType() == typeof(SwaggerIgnoreAttribute))
                        {
                            for (int i = 0; i < operation.RequestBody.Content.Values.Count; i++)
                            {
                                for (int j = 0; j < operation.RequestBody.Content.Values.ElementAt(i).Encoding.Count; j++)
                                {
                                    if (operation.RequestBody.Content.Values.ElementAt(i).Encoding.ElementAt(j).Key ==
                                        excludedPropertie.Name)
                                    {
                                        operation.RequestBody.Content.Values.ElementAt(i).Encoding
                                            .Remove(operation.RequestBody.Content.Values.ElementAt(i).Encoding
                                                .ElementAt(j));
                                        operation.RequestBody.Content.Values.ElementAt(i).Schema.Properties.Remove(excludedPropertie.Name);


                                    }
                                }
                            }

                        }
                    }
                }

            }
        }
    }
public class SwaggerIgnoreFilter : ISchemaFilter
    {
        public void Apply(OpenApiSchema schema, SchemaFilterContext schemaFilterContext)
        {
            if (schema.Properties.Count == 0)
                return;

            const BindingFlags bindingFlags = BindingFlags.Public |
                                              BindingFlags.NonPublic |
                                              BindingFlags.Instance;
            var memberList = schemaFilterContext.Type // In v5.3.3+ use Type instead
                                .GetFields(bindingFlags).Cast<MemberInfo>()
                                .Concat(schemaFilterContext.Type // In v5.3.3+ use Type instead
                                .GetProperties(bindingFlags));

            var excludedList = memberList.Where(m =>
                                                m.GetCustomAttribute<SwaggerIgnoreAttribute>()
                                                != null)
                                         .Select(m =>
                                             (m.GetCustomAttribute<JsonPropertyAttribute>()
                                              ?.PropertyName
                                              ?? m.Name.ToCamelCase()));

            foreach (var excludedName in excludedList)
            {
                if (schema.Properties.ContainsKey(excludedName))
                    schema.Properties.Remove(excludedName);
            }
        }

    }

然后,将它们都添加到启动类中以进行招摇配置:

services.AddSwaggerGen(options =>
{
   options.SchemaFilter<SwaggerIgnoreFilter>();
   options.OperationFilter<IgnorePropertyFilter>();
}

最后,您可以将 [SwaggerIgnore] 用于您不会在 swagger 中看到的每个属性:

public partial class ApplicationDocument : BaseModel
{
    public int id { get; set; }
    public int document_id { get; set; }
    public int application_id { get; set; }
        
    public string name { get; set; }
        
    public string documentUrl { get; set; }

    [SwaggerIgnore]
    public virtual Application application { get; set; }
    [SwaggerIgnore]
    public virtual Document document { get; set; }
}

推荐阅读