Cześć, od jakiegoś czasu przeglądam forum 4programmers i korzystam z jego zasobów, ale dopiero teraz postanowiłem założyć konto i poszukać pomocy w czymś, czego nie mogę znaleźć w internecie. Z góry zaznaczę, że jestem laikiem i zdaje sobie sprawę, że pewne części mojego kodu powinny wyglądać lepiej lub kompletnie inaczej.
Aktualnie uczę się tworząc proste API w którym mam różne relacje miedzy encjami, największy problem mam właśnie z tytułową relacją wiele do wielu i metodą POST.
Postaram się opisać, w czym leży mój problem:
Posiadam dwie klasy (Book i Author) i klasę łączącą (BookAuthor), które tworzą relacje wiele do wielu.
Oprócz tego mam kilka klas DTO. BookController z metodą POST i Profiler dla AutoMappera (wszystko poniżej).
Po wysłaniu zapytania POST do API mój wynik w JSON wygląda następująco:
JSON BODY
{
"title": "sample title5",
"authors": [
{ "authorId": 5 },
{ "authorId": 2 }
]
}
RESULT
{
"title": "sample title",
"authors": []
}
Chciałbym, aby wyglądało to tak: (tzn. zamiast pustej tablicy, wyświetlała się lista autorów)
{
"title": "sample title",
"authors": [
{
"authorId": 5,
"authorId": 2
},
}
**** KOD ****
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public ICollection<BookAuthor> BooksAuthors { get; set; }
}
public class Author
{
public int AuthorId { get; set; }
public string AuthorName { get; set; }
public string AuthorLastName { get; set; }
public ICollection<BookAuthor> BooksAuthors { get; set; }
}
public class BookAuthor
{
public int BookId { get; set; }
public Book Book { get; set; }
public int AuthorId { get; set; }
public Author Author { get; set; }
}
DTOs
public class BookForNewDto
{
public string Title { get; set; }
public ICollection<AuthorForNewBookDto> Authors { get; set; }
}
public class AuthorForNewBookDto
{
public int AuthorId { get; set; }
}
BookController // metoda POST
[HttpPost]
public async Task<IActionResult> AddBook([FromBody] BookForNewDto bookForNewDto)
{
var bookToCreate = _mapper.Map<Book>(bookForNewDto);
var bookToReturn = _mapper.Map<BookForNewDto>(bookToCreate);
var bookToAdd = await _context.Books.AddAsync(bookToCreate);
await _context.SaveChangesAsync();
var bookIdToAdd = bookToCreate.BookId;
var authorIdToAdd = bookForNewDto.Authors.Select(aa => aa.AuthorId).ToList();
foreach (var item in authorIdToAdd)
{
var bookAuthorToAdd = new BookAuthor()
{
BookId = bookIdToAdd,
AuthorId = item
};
var newBookAuthor = await _context.BooksAuthors.AddAsync(bookAuthorToAdd);
await _context.SaveChangesAsync();
}
return Ok(bookToReturn);
}
AutoMapper Profiler
CreateMap<BookForNewDto, Book>();
CreateMap<Book, BookForNewDto>()
.ForMember(dto => dto.PublisherId, opt => opt.MapFrom(x => x.PublisherId))
.ForMember(dto => dto.Authors, c => c.MapFrom(c => c.BooksAuthors.Select(cs => cs.Author).ToList()));
CreateMap<AuthorForNewBookDto, Author>()
.ForMember(dto => dto.AuthorId, opt => opt.MapFrom(x => x.AuthorId));
Sama funkcjonalność, jeśli chodzi o dodanie książki z listą autorów do bazy działa prawidłowo tzn. dodaje mi książkę do tabeli Books i dodają mi się nowe rekordy do tabeli BooksAuthors.
Jedyne co mnie dręczy to pusta lista 'authors' w wyniku JSON.
Mam nadzieje, że dobrze opisałem, w czym mam problem, a także liczę na wasze sugestie i dobre rady. Osobiście uważam, że popełniam jakiś błąd w kontrolerze albo w profilerze.
Pozdrawiam.