chumberjosh
chumberjosh

Reputation: 516

remove object from list and return as object .net core

So i'm trying to return some data from my API, it currently isn't returning in the way that I want it to, I want it to return as objects inside of an array but currently it is returning as objects inside of arrays inside of an array.

This is my code:

    [HttpGet("{CurrentUsername}")]
    public IEnumerable<IEnumerable<Message>> GetMyMessageList(string currentUsername)
    {
        var currentUser = _context.Users.FirstOrDefault(x => x.Username == currentUsername);

        var currentUserId = currentUser.Id;

        var messageList = _context.Messages
                    .Where(x => x.SenderId == currentUserId || x.RecipientId == currentUserId)
                    .OrderByDescending(x => x.DateTimeSent)
                    .GroupBy(x => new
                    {
                        Smaller = x.SenderId < x.RecipientId ? x.SenderId : x.RecipientId,
                        Greater = x.SenderId > x.RecipientId ? x.SenderId : x.RecipientId,
                    })
                    .Select(x => x.OrderByDescending(p => p.DateTimeSent).Take(1));

        return messageList;
    }

It currently looks like this:

[
    [
        {
            "id": 4,
            "senderId": 1,
            "recipientId": 3,
            "senderUsername": "jxchumber",
            "recipientUsername": "pavster31",
            "itemId": 0,
            "messageContentString": "hello1",
            "read": false,
            "dateTimeSent": "2020-12-14T22:23:55.1473414"
        }
    ],
    [
        {
            "id": 3,
            "senderId": 1,
            "recipientId": 9,
            "senderUsername": "jxchumber",
            "recipientUsername": "larsen",
            "itemId": 0,
            "messageContentString": "hello1",
            "read": false,
            "dateTimeSent": "2020-12-14T16:04:50.8232055"
        }
    ]
]

I want it to look like this:

[
    {
        "id": 4,
        "senderId": 1,
        "recipientId": 3,
        "senderUsername": "jxchumber",
        "recipientUsername": "pavster31",
        "itemId": 0,
        "messageContentString": "hello1",
        "read": false,
        "dateTimeSent": "2020-12-14T22:23:55.1473414"
    },
    {
        "id": 3,
        "senderId": 1,
        "recipientId": 9,
        "senderUsername": "jxchumber",
        "recipientUsername": "larsen",
        "itemId": 0,
        "messageContentString": "hello1",
        "read": false,
        "dateTimeSent": "2020-12-14T16:04:50.8232055"
    }
]

Upvotes: 2

Views: 286

Answers (1)

Andrew Williamson
Andrew Williamson

Reputation: 8691

You can use SelectMany to select an enumerable property from each row, and flatten them all into one list:

[HttpGet("{CurrentUsername}")]
public IEnumerable<Message> GetMyMessageList(string currentUsername)
{
    var currentUser = _context.Users.FirstOrDefault(x => x.Username == currentUsername);

    var currentUserId = currentUser.Id;

    var messageList = _context.Messages
                .Where(x => x.SenderId == currentUserId || x.RecipientId == currentUserId)
                .OrderByDescending(x => x.DateTimeSent)
                .GroupBy(x => new
                {
                    Smaller = x.SenderId < x.RecipientId ? x.SenderId : x.RecipientId,
                    Greater = x.SenderId > x.RecipientId ? x.SenderId : x.RecipientId,
                })
                .SelectMany(x => x.OrderByDescending(p => p.DateTimeSent).Take(1));

    return messageList;
}

Alternatively, you can specify that you are selecting the first item instead of a collection with FirstOrDefault:

    var messageList = _context.Messages
        .Where(x => x.SenderId == currentUserId || x.RecipientId == currentUserId)
        .OrderByDescending(x => x.DateTimeSent)
        .GroupBy(x => new
        {
            Smaller = x.SenderId < x.RecipientId ? x.SenderId : x.RecipientId,
            Greater = x.SenderId > x.RecipientId ? x.SenderId : x.RecipientId,
        })
        .Select(x => x.OrderByDescending(p => p.DateTimeSent).FirstOrDefault());

However, this may include nulls in the output if the filtered collection contains no elements.

Upvotes: 2

Related Questions