如何忽略 Swagger 正文输入上的属性但仍显示在响应中?

问题描述 投票:0回答:3

我正在使用 Swashbuckle 和 Swagger UI 自动生成 API 文档。

我的人员端点使用以下 PersonViewmodel:

public int? ID { get; set; }
public string Name { get; set; }

我的端点方法采用 PersonViewmodel 作为主体,并使用 IActionResult 返回 PersonViewmodel。但是,我不希望用户定义由业务逻辑生成的 ID。在代码中,如果设置了 ID,它将被忽略。

如何更改 Swagger UI,使其不在正文输入的示例值中显示 ID,但仍显示响应的示例值的 ID?

我发现了很多从 Swagger UI 中完全删除属性的方法,例如

[JsonIgnore]
或将属性设置为
internal
private
。但是如何从 swagger 中的输入示例中删除属性,但将其保留在输出/响应示例中?

c# asp.net-core swagger swagger-ui swashbuckle
3个回答
2
投票

请使用属性上方的属性

[BindNever]
,例如

[BindNever]
public int? Id {get;set;}

另外,请检查您是否使用 Newtonsoft.Json 进行序列化,这可能是您的 System.Text 的

JsonIgnore
属性不起作用的原因。


1
投票

现在有更好的方法了。有两件事你需要做

  1. 使用 Swashbuckle.AspNetCore.Annotations 中的 SwaggerSchema 进行注释;
    [SwaggerSchema(ReadOnly = true)]
    public int Id { get; set; }
  1. 在 AddSwaggerGen 中启用注释
    builder.Services.AddSwaggerGen(options =>
    {
        options.EnableAnnotations();
    });

文档

中查看更多相关信息

0
投票

我尝试了很多不同的选择,但没有一个适合我的需求。 根据 GitHub issues,

[SwaggerSchema(ReadOnly = true)]
似乎不起作用;使用架构处理器也不起作用,尤其是在处理 OData 控制器时。

我最终使用

IDocumentFilter
解决了这个问题。

文档过滤器:

using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

/// <summary>
/// Makes sure readonly parameters are not considered while creating/updating/deleting an entity
/// </summary>
public class SwaggerRemoveReadonlyParameters_DocumentFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        foreach (var apiDesc in context.ApiDescriptions)
        {
            // Ignore GET method (we DO want readonly parameters to be displayed, in this case)
            if (apiDesc.HttpMethod == "GET")
                continue;

            var readonlyParameters = apiDesc.ParameterDescriptions.Where(ShouldBeFilteredOut);

            foreach (var readonlyParameter in readonlyParameters.ToArray())
                apiDesc.ParameterDescriptions.Remove(readonlyParameter);
        }
    }

    private static bool ShouldBeFilteredOut(ApiParameterDescription parameter)
    {
        // Only consider model binding
        if (parameter.Source.DisplayName != "ModelBinding")
            return false;

        // Identify read only properties... (sometimes Swashbuckle/Swagger shows them anyway, especially in OData controllers)
        if (parameter.ModelMetadata?.IsReadOnly == true)
            return true;

        if (parameter.ModelMetadata is not DefaultModelMetadata modelMetadata)
            return false;

        // ...and properties/fields explicitly marked as readonly by decorating them with the [SwaggerReadOnly] attribute
        if (modelMetadata.Attributes.Attributes.Any(a => a is SwaggerReadOnlyAttribute))
            return true;

        return false;
    }
}

属性:

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

通过以下方式注册您的文档过滤器:

Services.AddSwaggerGen(options => options.DocumentFilter<SwaggerRemoveReadonlyParameters_DocumentFilter>());

像这样装饰你的只读属性:

public class MyEntity
{
    [SwaggerReadOnly] // Hidden by the Document Filter
    public Guid Id { get; set; }

    public string Name { get; set; }

    public string? Description { get; set; }

    [SwaggerReadOnly] // Hidden by the Document Filter
    public DateTime LastModified { get; set; }

    // Automatically hidden by the Document Filter
    public bool HasDescription => !string.IsNullOrEmpty(Description);
}
© www.soinside.com 2019 - 2024. All rights reserved.