【问题标题】:Web Api: Return JSON with EF Included Member Field Count but not Member Object DataWeb Api:返回包含 EF 的成员字段计数但不包含成员对象数据的 JSON
【发布时间】:2017-10-11 02:38:33
【问题描述】:

场景:投诉对象可以有很多投票。在所有投诉的 GET 请求中,我想返回投票计数,而不是 API 响应中带有投诉的每个单独的投票对象。

这是主要的类:

//Model: Complaint.cs
public class Complaint
{
    public int Id { get; set; }
    public string Summary { get; set; }
    public List<Vote> Votes { get; set; }
    public int UpVoteCount=> Votes.Count(v => v.IsUpvote);
    public ApplicationUser Creator { get; set; }
}


//Model: Vote.cs
public class Vote
{
    public int Id { get; set; }
    public bool IsUpVote{ get; set; }
    public Complaint Complaint { get; set; }
    public ApplicationUser Creator { get; set; }
}


//DbContext: AppDbContext.cs
....
public IQueryable<Complaint> ComplaintsWithData =>
        Complaint
            .Include(complaint => complaint.Votes)
            .AsNoTracking();

//ApiController: ComplaintsController.cs
[HttpGet]
public IEnumerable<Complaint> GetComplaints()
{
      return _context.ComplaintsWithData.ToList();
}

在当前的 JSON 响应中,我获得了投票计数,但我也获得了每个投票对象的详细信息(在此调用中我不需要)。

目前的回应:

{
        "id": 2,
        "summary": "House was Stolen",
        "votes": [
            {
                "id": 146,
                "isUpvote": false,
                "creator": null
            },
                        {
                "id": 147,
                "isUpvote": false,
                "creator": null
            },
            ....
            ....
            ....
        ],
        "upVoteCount": 211,
    }

期望的响应:

{
        "id": 2,
        "summary": "House was Stolen",
        "upVoteCount": 211,
    }

我需要在 AppDbContext.cs 文件中包含 .Include(complaint => 投诉.Votes),以便我可以实际加载投票以确定投票计数。

我不想将投票计数存储为实际的数据库列。

任何建议将不胜感激!

我正在使用 .NET Core 2.0 Web API 和 Entity Framework Core。

提前致谢。

【问题讨论】:

  • 您好,您不应该通过 webapi 公开您的数据库对象。您应该创建 DTO(数据传输对象),一旦从数据库中获取结果,您应该将结果映射到 DTO 并返回 DTO 作为响应。如果您确实需要公开您的数据库对象,那么您可以尝试在 List Vots 上添加 [JsonIgnore] 属性。我鼓励你选择 DTO。

标签: entity-framework-core asp.net-core-webapi


【解决方案1】:

您可以在您的班级上使用 OptIn 进行成员序列化:

//..
using Newtonsoft.Json;
//..

[JsonObject(MemberSerialization.OptIn)]
public class Complaint
{
    [JsonProperty("id")]
    public int Id { get; set; }
    [JsonProperty("summary")]
    public string Summary { get; set; }
    public List<Vote> Votes { get; set; }
    [JsonProperty("upVoteCount")]
    public int UpVoteCount=> Votes.Count(v => v.IsUpvote);
    public ApplicationUser Creator { get; set; }
}

【讨论】:

    【解决方案2】:

    可能是这样的:

    public List<Complaint> ComplaintsWithData()
    {
        return this.DbContext.Complaints
            .Include(complaint => complaint.Votes)
            .Select(p => new Complaint
            {
                Id = p.Id,
                IsUpVote = p.IsUpVote,
                UpVoteCount = p.Votes.Count
            }).ToList();
    }
    

    【讨论】:

      【解决方案3】:

      有多种选择。以下是其中两个:

      您可以考虑添加视图模型 - 具有您希望返回 UI 的确切属性集的类。您只需将您的实体记录映射到它们

      或者只是标记您想要隐藏的属性,以免序列化到您的JSONXML 端点响应带有NonSerialized 属性

      public class Complaint
      {
          public int Id { get; set; }
          public string Summary { get; set; }
          [NonSerialized]
          public List<Vote> Votes { get; set; }
          public int UpVoteCount=> Votes.Count(v => v.IsUpvote);
          public ApplicationUser Creator { get; set; }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-05-13
        • 1970-01-01
        • 2014-07-03
        • 1970-01-01
        • 2021-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-24
        相关资源
        最近更新 更多