0

I have a small Web Api method. How can I map properties in GetBooks method with Automapper? I have tried the solution here .

I have tried

 return from c in db.Books select Mapper.Map<BookDTO>(c);

But it didnt work. Here is my complete code;

     //GET: api/Books
      public IQueryable<BookDTO> GetBooks()
      {
        var books = from b in db.Books
                    select new BookDTO()
                    {
                        Id = b.Id,
                        Title = b.Title,
                        AuthorName = b.Author.Name
                    };

        return books;
    }

Book.cs

 public class Book
{
    public int Id { get; set; }
    [Required]
    public string Title { get; set; }
    public int Year { get; set; }
    public decimal Price { get; set; }
    public string Genre { get; set; }

    // Foreign Key
    public int AuthorId { get; set; }
    // Navigation property
    public Author Author { get; set; }
}

BookDTO.cs

 public class BookDTO
   {
    public int Id { get; set; }
    public string Title { get; set; }
    public string AuthorName { get; set; }
   }

thanks in advance.

Community
  • 1
  • 1
oneNiceFriend
  • 6,691
  • 7
  • 29
  • 39
  • 1
    "But not succesfull" is not a description of the problem. – Jeroen Vannevel Feb 19 '16 at 15:25
  • You are right. I was in a hurry thats why I wrote like that. I mean I tried the methods on the link I have given. And it didnt work. I implemented this code on to mine. return from c in context.Customers select Mapper.Map(c); – oneNiceFriend Feb 19 '16 at 16:16

2 Answers2

2
  1. Config Map between Book and BookDTO in Global.asax.cs or Startup.cs file:

    Mapper.CreateMap<Book, BookDTO>();
    
  2. Map db.Books in GetBooks() method:

    using AutoMapper.QueryableExtensions;
    
    ...
    
    public IQueryable<BookDTO> GetBooks()
    {
        return db.Books.ProjectTo<BookDTO>();
    }
    
Arturo Menchaca
  • 15,783
  • 1
  • 29
  • 53
  • Yes, It worked, really amazing. Do you have any idea about How does Automapper knows BookDTO.AuthorName is Book.Author.Name ? – oneNiceFriend Feb 19 '16 at 16:17
  • @OneNiceFriend: If for any property on the destination type a property does not exist on the source type, AutoMapper splits the destination member name into individual words (by PascalCase conventions), This link explains it better: https://github.com/AutoMapper/AutoMapper/wiki/Flattening – Arturo Menchaca Feb 19 '16 at 16:26
1

You need projection. See Automapper - Projection

Mapper.CreateMap<Book, BookDTO>()
    .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
    .ForMember(dest => dest.Title, opt => opt.MapFrom(src => src.Title))
    .ForMember(dest => dest.AuthorName, opt => opt.MapFrom(src => src.Author.Name));

IEnumerable<Book> books = db.Books.Cast<Book>();
// assuming Books implements IEnumerable
BookDTO result = Mapper.Map<Book, BookDTO> books;

I'm not sure if you need the projection lines for properties Id and Title. Read the documentation of AutoMapper to see what defaults it uses.

Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116