Search code examples
c#restlinqasp.net-coreasp.net-apicontroller

How to return an array of grouped items?


I have a simple GET request working to return all of my elements. But I can't seem to figure out how to return those elements in a grouped array, grouped by name and date.

My model:

public class Event
{
   [Key]
   public long ID { get; set; }

   [Required]
   public DateTime date { get; set; }

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

This is my GET request to return all elements:

[Route("api/events")]
[HttpGet]
public async Task<ActionResult<IEnumerable<Event>>> GetEvents()
{
   return await _context.Events.ToListAsync();
}

Solution

  • You could define a DTO like this:

    public class GroupedEventsDto
    {
        public DateTime Date { get; set; }
        public string Name { get; set; }
    
        // although you already know date and name, 
        // so you could have the list of IDs only
        public List<Event> Events { get; set; }
    }
    

    and do it simply like:

    [HttpGet("api/events")]
    public async Task<ActionResult<IEnumerable<GroupedEventsDto>>> GetEvents()
    {
        var events = await context.Events.ToArrayAsync();
    
        var data = events 
           .GroupBy(x => new { x.date, x.name })
           .Select(grp => new GroupedEventsDto
           {
              Date = grp.Key.date,
              Name = grp.Key.name,
              Events = grp.ToList()
            })
            .ToList();
    
        return data;
    }
    

    This would generate a JSON like

    [
        {
            "Name": "a",
            "Date": "2020-08-22",
            "Events": [
                {
                    "Name": "a",
                    "Date": "2020-08-22",
                    "Id": 1
                }, ...
            ]
        },
        {
            "Name": "b",
            "Date": "2020-08-22",
            "Events": [
                {
                    "Name": "b",
                    "Date": "2020-08-22",
                    "Id": 2
                }, ...
            ]
        },
        ...
    ]
    

    Of course, which properties you end up needing would change in GroupedEventsDto