SwaggerSchema 不适用于我自己的对象

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

我正在使用 ASP.NET 创建 Web API。为了向用户公开我的数据库模型,我创建了数据模板对象,以便我可以显示/隐藏 swagger 架构中的属性。

问题是,如果我想区分 POST 和 GET 方法,我认为这是不可扩展的。

假设我有一个博客模型,其中有标识符、名称和创建者。当我创建一个新博客时,我只想设置博客的名称。另一方面,我想在发送 GET 请求时读取其他属性。

数据库模型

public class Blog
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    [ForeignKey("CreatorId")]
    public Users Creator { get; set; }
    public int CreatorId { get; set; }
}

数据模板对象

public class BlogDto
{
    public int Id { get; set; }

    public string Name { get; set; }

    public Users Creator { get; set; }
}

现在,如果我运行此代码,发布请求会要求我设置所有创建者对象,以及博客 ID(应由实体框架设置)。

我发现我可以通过设置

[SwaggerSchema(ReadOnly = true)]
来隐藏标识符字段。不幸的是,此属性不适用于我的 Creator 属性。

也就是说,如果我将 BlogDto 设置为:

public class BlogDto
{
    [SwaggerSchema(ReadOnly = true)]
    public int Id { get; set; }

    public string Name { get; set; }

    [SwaggerSchema(ReadOnly = true)]
    public Users Creator { get; set; }
}

POST 方法的 Swagger 助手将是: SwaggerOutput

我希望请求正文只是:

{
  "name": "string"
}

(仅当属性 SwaggerSchema 位于我创建的对象上时才会触发此问题)。

我尝试过自定义 Json 序列化器、更改 SchemaFilter、使用

[JsonIgnore]
[ReadOnly(true)]
。我发现的解决方法是创建一个仅包含
string Name { get; set; }
属性的 BlogPostDto 和包含所有三个属性的 BlogGetDto,但我想知道是否可以仅使用一个 Dto 来实现这一点。

asp.net swagger
2个回答
4
投票

终于找到解决方案了。

swagger 存储库中也报告了此问题(嵌套对象上的只读),但我无法理解 Asp.Net 的等效项。

但是我尝试将

[SwaggerSchema(ReadOnly = true)]
添加到课程本身。我不知道为什么这会起作用,或者即使它在其他地方产生问题。无论如何,这是我的方法,因为我在这里无法收到任何其他回复。

简单来说,我所做的是为用户模型添加一个新的数据模板对象:

[SwaggerSchema(ReadOnly = true)]
public class UserDto
{
    [SwaggerSchema(ReadOnly = true)]
    public int Id { get; set; }

    public string Username { get; set; }

    public string Email { get; set; }
}

请注意,我将 SwaggerSchema 属性添加到该类中。然后我可以删除 BlogDto Creator 属性的属性:

public class BlogDto
{
    [SwaggerSchema(ReadOnly = true)]
    public int Id { get; set; }

    public string Name { get; set; }

    public UserDto Creator { get; set; }
}

我想我必须将该属性添加到我为项目创建的每个 DTO 中。

我仍然愿意进一步讨论。

谢谢。


0
投票

我回顾了 Swashbuckle.AspNetCore.Annotations 中的 AnnotationsSchemaFilter

我找不到任何地方从架构中删除属性(schema.Properties.Remove(excludedName)

我创建了另一个过滤器并在 Swashbuckle.AspNetCore.Annotations 中使用 SwaggerSchemaAttribute

public class SwaggerIgnoreFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (schema?.Properties == null)
        {
            return;
        }

        const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
        var memberList = context.Type
            .GetFields(bindingFlags).Cast<MemberInfo>()
            .Concat(context.Type.GetProperties(bindingFlags));

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

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

public static class StringExtension
{
    public static string ToCamelCase(this string str)
    {
        if (!string.IsNullOrEmpty(str) && str.Length > 1)
        {
            return char.ToLowerInvariant(str[0]) + str.Substring(1);
        }
        return str.ToLowerInvariant();
    }
}

并在program.cs中添加以下内容

builder.Services.AddSwaggerGen(options =>
{
    options.SchemaFilter<SwaggerIgnoreFilter>();
}

工作完美

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