【问题标题】:EF and [JsonIgnore]: Why do I get an empty dictionary when using an existing type, but not when using an anonymous type?EF 和 [JsonIgnore]:为什么我在使用现有类型时得到空字典,但在使用匿名类型时却没有?
【发布时间】:2021-12-23 05:46:19
【问题描述】:

问题

当使用匿名类型时它可以工作,但当使用与匿名类型相同的ClientGroupView 类型时则不行。为什么?

我怀疑这与 [JsonIgnore] 属性有关 - 它以某种方式持续存在于 类型化对象,但不存在于 匿名对象

背景

我在 ClientsClientGroups 之间建立了多对多关系,并且控制器返回给定客户端的组。

当我使用类型化对象时,控制器方法返回带有空字典的Json,但如果我使用匿名对象,则返回预期的Json。我使用 .NET 5 和 .Net 6 得到相同的结果。

使用匿名对象时,返回的Json为:

[{
    "group":{ "clientGroupId":1, "groupName":"ClientGroup1" },
    "permissions":{ "rClientGroupClientId":1, "clientGroupId":1, "clientId":1 }
}]

当使用 ClientGroupView 类型的对象(不包含任何 [JsonIgnore] 属性)时,返回的 Json 为:

[{}]

我这两种情况result是一样的,在转换为Json之前,返回Ok(result)

控制器

返回给定ClientId信息的控制器方法:

[HttpGet]
[Route("{id}")]
public async Task<IActionResult> GetClientGroups(int id)
{
    var client = await db.Clients.FindAsync(id);
    if (client == null)
        return NotFound();

    // Works when using an anonymous type - the Json dictionary is not empty.
    var groups = db.Entry(client)
            .Collection(r => r.XClientGroups)
            .Query()
            .Include(r => r.ClientGroup)
            .Select(r => new { r.ClientGroup, r });

    // But fails when not using an anonymous type - the json dictionary is empty.
    //var groups = db.Entry(client)
    //        .Collection(r => r.XClientGroups)
    //        .Query()
    //        .Include(r => r.ClientGroup)
    //        .Select(r => new ClientGroupView(r.ClientGroup, r));
            
    var result = await groups.ToListAsync();
    if (result == null || result.Count <= 0)
        return NotFound();
    return Ok(result);
}

Client

public class Client
{
    public int ClientId { get; set; }
    public string ClientName { get; set; } = string.Empty;

    [JsonIgnore]
    public virtual ICollection<X_ClientGroup_Client> XClientGroups { get; set; }

    public Client()
    {
        XClientGroups = new HashSet<X_ClientGroup_Client>();
    }
}

ClientGroup

public class ClientGroup
{
    public int ClientGroupId { get; set; }
    public string GroupName { get; set; }

    [JsonIgnore]
    public virtual ICollection<X_ClientGroup_Client> XClients { get; set; }

    public ClientGroup()
    {
        XClients = new HashSet<X_ClientGroup_Client>();
    }
}

X_ClientGroup_Client

ClientClientGroup 之间的多对多关系:

public class X_ClientGroup_Client
{
    public int RClientGroupClientId { get; set; }
    public int ClientGroupId { get; set; }
    public int ClientId { get; set; }

    [JsonIgnore]
    public ClientGroup ClientGroup { get; set; }
    [JsonIgnore]
    public Client Client { get; set; }
}

ClientGroupView

这里是对应匿名对象的ClientGroupView。它不包含任何[JsonIgnore] 属性:

public class ClientGroupView
{
    public ClientGroup Group;
    public X_ClientGroup_Client Permissions;
    public ClientGroupView(ClientGroup group, X_ClientGroup_Client permissions)
    {
        this.Group = group;
        this.Permissions = permissions;
    }
}

如果我删除构造函数并像使用匿名对象一样构造对象,结果是一样的。

一个解决方案是更改ClientGroupView 以包含字段而不是类,但我更喜欢它包含类而不是类的字段,因为它更易于维护:

// I do not want to use this version of ClientGroupView
public class ClientGroupView
{
    public int RClientGroupClientId { get; set; }
    public int ClientId { get; set; }
    public int ClientGroupId { get; set; }
    public string GroupName { get; set; }

    public ClientGroupView(ClientGroup clientgroup, X_ClientGroup_Client permissions)
    {
        RClientGroupClientId = permissions.RClientGroupClientId;
        ClientId = permissions.ClientId;
        ClientGroupId = clientgroup.ClientGroupId;
        GroupName = clientgroup.GroupName;
    }
}

我不想使用这个版本的原因是因为它需要更多的维护因为控制器是内部使用的,即我不需要使用 DTO。

【问题讨论】:

  • 如何(1)制作具体的类字段属性,以及(2)使用初始化器(new ClientGroupView { Group = ..., ... })而不是构造器?
  • @IvanStoev 我已经尝试过了,它产生了相同的结果。
  • 我试过这个模型,但无法重现 - 无论是在 EFC 5.0 还是 EFC 6.0 中
  • @IvanStoev 我找到了一个修复程序,我将其添加到问题中,但我对此并不满意。感谢您的帮助。
  • @IvanStoev 感谢您对其进行测试,这让我意识到这可能与我省略的 [JsonIgnore] 标记有关。我已经修改了问题。

标签: c# asp.net-mvc .net-core .net-5


【解决方案1】:

ClientGroupView.GroupClientGroupView.Permissions 是字段,而不是属性。

添加{ get; set; }

【讨论】:

猜你喜欢
  • 2016-05-12
  • 2016-08-02
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-28
相关资源
最近更新 更多