【问题标题】:ASP.NET Core Web API Swagger docs incorrect with reference loop between classesASP.NET Core Web API Swagger 文档与类之间的引用循环不正确
【发布时间】:2016-10-27 15:15:05
【问题描述】:

我的应用程序中有以下类:

public class Person
{
    public int Id { get; set; }
    public Guid PublicKey { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public virtual List<Order> Orders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
    public virtual Person Person { get; set; }
    public int PersonId { get; set; }
}

以及以下 API 控制器,它只获取所有人的列表(总是有 2 个,每个人总是有 3 个订单):

[Route("api/[controller]")]
public class PeopleController : Controller
{
    // GET api/people
    [HttpGet]
    public List<Person> Get()
    {
        PeopleService people = new PeopleService();

        return people.GetAllPeople();
    }
}

我应该指出,我从一开始就遇到了 Order 类上的导航属性引用拥有它的 Person 的问题,因为 Json.NET 格式化程序不喜欢这个开箱即用,你必须将其配置为忽略参考循环。我在 Startup.cs 中这样做了:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddJsonOptions(o => 
        {
            o.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.None;
            o.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        });

    services.AddSwaggerGen();
}

这很好用,当我提出请求时,我得到以下响应:

[
    {
        "orders": [
            {
                "id": 1,
                "date": "2016-10-26T17:16:35.21",
                "personId": 1
            },
            {
                "id": 2,
                "date": "2016-10-26T17:16:35.21",
                "personId": 1
            }
        ],
        "id": 1,
        "publicKey": "b6a7c21c-86d8-4bb9-9a05-bd394e6ed0c9",
        "firstName": "Lauren",
        "lastName": "Phillips"
    },
    {
        "orders": [
            {
                "id": 3,
                "date": "2016-10-26T17:16:35.21",
                "personId": 2
            },
            {
                "id": 4,
                "date": "2016-10-26T17:16:35.21",
                "personId": 2
            }
        ],
        "id": 2,
        "publicKey": "8b5a90b4-a9a2-4a0e-96dd-529962972456",
        "firstName": "Robert",
        "lastName": "West"
    }
]

我正在使用Swashbuckle 为我的 API 生成 Swagger 文档。 Swashbuckle/Swagger 生成的“示例值”似乎在每个订单中再次包含了 Person:

[
    {
        "id": 0,
        "publicKey": "string",
        "firstName": "string",
        "lastName": "string",
        "orders": [
            {
                "id": 0,
                "date": "2016-10-27T14:19:52.437Z",
                "person": {
                    "id": 0,
                    "publicKey": "string",
                    "firstName": "string",
                    "lastName": "string",
                    "orders": [
                        {}
                    ]
                },
                "personId": 0
            }
        ]
    }
]

我不希望使用 API 的人期望该人再次包含在每个订单中,尤其是因为这不是您实际得到的,因为我将其配置为忽略上面的引用循环。我想这个问题与参考循环有关,但我不确定。有谁知道如何解决这个问题?

【问题讨论】:

    标签: asp.net-web-api asp.net-core swagger swagger-ui swashbuckle


    【解决方案1】:

    也许,您可以使用属性 - [JsonIgnore] 在 swagger 文档中不显示它

    【讨论】:

    • 谢谢,这确实有效,但是 Person 将永远被排除在订单之外。很可能在某些时候我需要得到一个特定的订单,并期望它是 Person 来的。我很感激我的困难,我刚刚开始一个大项目,并且想在以后引起我自己的问题之前解决所有这些问题。
    • @Ben,我不确定您为什么在 Order 类中再次引用了 Person 对象。但是,如果 Order 对象在从 Person 类的上下文中引用时永远不会具有 Person 属性,那么您实际上可以将 Order 拆分为两个类 - OrderBasicDetails(名称可以是任何有意义的名称)和 Order。 OrderBasicDetails 将具有除 Person 之外的所有属性,并且 Order 类将从 Basic 继承并具有 person 属性。
    • 虽然在 OOP 中提供父对象和子对象之间的导航属性是相当标准的,但它允许非常简单的对象遍历。在这种情况下,它们都是实体框架实体,因此从 Order 返回到 person 的引用实际上代表了外键关系