Reputation: 516
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
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