Swagger / Swashbuckle 参考循环问题

Swagger / Swashbuckle reference loop problem

我正在使用 Swagger/Swashbuckle 作为 ASP.NET Core 3.1 API。

Swagger.json 看起来不错,但是 swaggerUI 的模型引用有问题。 "example value" 部分非常大,因为正在加载所有模型引用。

SwaggerUI

正如您在图片中看到的那样,"createdBy" 引用了 "personContactyCreatedBy",然后又引用了 "straßeNr",依此类推。 看起来它也循环回到 "createdBy" 因为它几乎用于任何模型。 这个问题导致 swaggerUI 非常慢。我尝试了 redoc UI,它甚至没有停止加载。

Newtonsoft 自参考循环已禁用。 有没有办法在 swashbuckle and/or swaggerUI 中禁用那些大 references/loops?

swaggerjson:"createdBy": { "$ref": "#/definitions/User" },

您可以在此处找到 fullswagger.json:Pastebin

您可以将 [JsonIgnore] 添加到您不想在您的模型中使用的属性。这可能会帮助您减少此类循环。 或者,您可以尝试使用

来限制模型的深度
app.UseSwaggerUI(c =>
{
    c.DefaultModelRendering(ModelRendering.Model);
    c.DefaultModelExpandDepth(1); 
});

下面是一个简单的解决方法:

1.Install Swashbuckle.AspNetCore.SwaggerGen 5.0.0-rc5

2.Custom SwaggerExcludeAttribute:

[AttributeUsage(AttributeTargets.Property)]
public class SwaggerExcludeAttribute : Attribute 
{ 
}

3.Custom SwaggerExcludeFilter:

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

        var excludedProperties =
            context.Type.GetProperties().Where(
                t => t.GetCustomAttribute<SwaggerExcludeAttribute>() != null);

        foreach (var excludedProperty in excludedProperties)
        {
            var propertyToRemove =
                schema.Properties.Keys.SingleOrDefault(
                    x => x.ToLower() == excludedProperty.Name.ToLower());

            if (propertyToRemove != null)
            {
                schema.Properties.Remove(propertyToRemove);
            }
        }
    }
}

4.Register 在 Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
        c.SchemaFilter<SwaggerExcludeFilter>();
    });

    services.AddDbContext<WebApi3_1Context>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("WebApi3_1Context")));            
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    });
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

5.Test 我的模特:

public class Test
{
    public int Id { get; set; }
    public string Name { get; set; }
    [SwaggerExclude]
    public Item Item { get; set; }
}
public class Item
{
    public int Id { get; set; }
    public string ItemName { get; set; }
    public List<Person> Person { get; set; }
}
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}