I just started playing with the WebAPI template in VS2017 ASP.NET Core using Entity Framework Core, and I'm trying to figure out the best way to return a subset of an object's properties for a particular Get request.
I used the built in scaffolding to generate a controller initially, and the Get
request method it generated initially looked like this:
[HttpGet]
public IEnumerable<Person> GetPeople()
{
return _context.People;
}
My problem was that Person
has a child class that I don't want included when someone makes a call to GetPeople()
.
Since I don't want to return an anonymous object, I instead added a stripped down class in the controller called PersonInfo
that has only the properties I want to be returned, like this:
public class PersonInfo
{
public int id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string AD { get; set; }
}
and then I updated the GetPeople()
method to this:
[HttpGet]
public IEnumerable<PersonInfo> GetPeople()
{
List<PersonInfo> pi = new List<PersonInfo>();
foreach(var person in _context.People
.Select(p => new { p.id, p.FirstName, p.LastName, p.AD})
.ToList())
{
PersonInfo newPerson = new PersonInfo();
newPerson.id = person.id;
newPerson.FirstName = person.FirstName;
newPerson.LastName = person.LastName;
newPerson.AD = person.AD;
pi.Add(newPerson);
}
return pi;
}
This works fine, it just feels horribly inefficient. There's got to be a better way, right?
That indeed is horribly inefficient. The method should look like this:
[HttpGet]
public async Task<IEnumerable<PersonInfo>> GetPeople()
{
return await _context.People
// select the data you want directly
.Select(p => new PersonInfo
{
id = p.id,
FirstName = p.FirstName,
LastName = p.LastName,
AD = p.AD
})
// always use the asynchronous version of EF Core extension methods
.ToListAsync();
}
By the way, you should get used to using the IActionResult
interface in ASP.NET Core. That allows you to easily customize the status code and how the data is returned. It's much more preferable to use something like:
[HttpGet]
public async Task<IActionResult> GetPeople()
{
var data = await _context.People
// select the data you want directly
.Select(p => new PersonInfo
{
id = p.id,
FirstName = p.FirstName,
LastName = p.LastName,
AD = p.AD
})
// always use the asynchronous version of EF Core extension methods
.ToListAsync();
return Json(data);
}