Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Include only one property, not entire database row

Model:

public class Word
{
    public int ID { get; set; }
    public string Title { get; set; }
    public DateTime? WhenCreated { get; set; }
    public ApplicationUser Author { get; set; }

    [NotMapped]
    public string AuthorName
    {
        get
        {
            if (Author != null)
            {
                return Author.UserName;
            }
            else {
                return "";
            }
        }
    }

    public List<Definition> Definitions { get; set; }
}

Controller:

[HttpGet]
    public IEnumerable<Word> Get()
    {
        return _db.Words.Include(x=>x.Author).ToList();
    }

My Controller now returns entire ApplicationUser class which is one of properties of Word. I want to send only one property of ApplicationUser: UserName. How can I do that?

I've added AuthorName, which would return only data that I want from ApplicationUser. Unfortunately I still have to .Include(x=>x.Author) to make this property work. Can I somehow omit including Author in process of data serialization (to hide it when sending data to user)?

I know I can use .Select() method, but it requires me to type all properties I will need. If I modify my Model in the future, I will need to update all those .Select() which will would be inconvenient and waste of time.

How would you solve that?

like image 615
Piotrek Avatar asked Oct 22 '16 12:10

Piotrek


2 Answers

You need to create a Dto object and assign the values to it and return the Dto instead.

Dto

public class WordDto 
{
    public string Title { get; set; }
    public DateTime? WhenCreated { get; set; }
    public string AuthorName { get; set; }
}

Then in your action

[HttpGet]
public async Task<IEnumerable<WordDto>> Get()
{
    return _db.Words
              .Include(x=>x.Author)
              .Select(x =>
                  new WordDto 
                  {
                      Title = x.Title,
                      DateTime = x.WhenCreated,
                      AuthorName = x.Author?.UserName ?? string.Empty
                  }
              )
              .ToListAsync();
}
like image 148
Tseng Avatar answered Sep 26 '22 14:09

Tseng


You can try it as shown below.

Note : You don't need to use Include here.

    [HttpGet]
    public async Task<IEnumerable<Word>> Get()
    {
        return _db.Words.Select(x => new  
                      {
                          Word = x,
                          AuthorName = x.Author.UserName
                      }
                  ).ToList();
    }
like image 36
Sampath Avatar answered Sep 25 '22 14:09

Sampath