diff --git a/exercise.webapi/DTO/AuthorDto.cs b/exercise.webapi/DTO/AuthorDto.cs new file mode 100644 index 0000000..3d29766 --- /dev/null +++ b/exercise.webapi/DTO/AuthorDto.cs @@ -0,0 +1,26 @@ +using exercise.webapi.Models; +using System.Text.Json.Serialization; + +namespace exercise.webapi.DTO +{ + public class AuthorDto + { + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public string Email { get; set; } + + public ICollection Books { get; set; } = new List(); + + public AuthorDto(Author author, List books) + { + Id = author.Id; + FirstName = author.FirstName; + LastName = author.LastName; + Email = author.Email; + Books = books; + + } + + } +} diff --git a/exercise.webapi/DTO/BookDto.cs b/exercise.webapi/DTO/BookDto.cs new file mode 100644 index 0000000..13613ee --- /dev/null +++ b/exercise.webapi/DTO/BookDto.cs @@ -0,0 +1,20 @@ +using exercise.webapi.Models; + +namespace exercise.webapi.DTO +{ + public class BookDto + { + public int Id { get; set; } + public string Title { get; set; } + public int AuthorId { get; set; } + public string AuthorName { get; set; } + + public BookDto(Book book) + { + Id = book.Id; + Title = book.Title; + AuthorId = book.AuthorId; + AuthorName = $"{book.Author.FirstName} {book.Author.LastName}"; + } + } +} diff --git a/exercise.webapi/Endpoints/AuthorApi.cs b/exercise.webapi/Endpoints/AuthorApi.cs new file mode 100644 index 0000000..61e2a13 --- /dev/null +++ b/exercise.webapi/Endpoints/AuthorApi.cs @@ -0,0 +1,23 @@ +using exercise.webapi.Repository; + +namespace exercise.webapi.Endpoints +{ + public static class AuthorApi + { + public static void ConfigureAuthorApi(this WebApplication app) + { + app.MapGet("/authors", GetAll); + app.MapGet("/author", Get); + } + public static async Task GetAll(IBookRepository repo) + { + var authors = repo.GetAllAuthors(); + return TypedResults.Ok(authors); + } + public static async Task Get(IBookRepository repo, int id) + { + var author = repo.GetAuthor(id); + return TypedResults.Ok(author); + } + } +} diff --git a/exercise.webapi/Endpoints/BookApi.cs b/exercise.webapi/Endpoints/BookApi.cs index 6758215..9976f41 100644 --- a/exercise.webapi/Endpoints/BookApi.cs +++ b/exercise.webapi/Endpoints/BookApi.cs @@ -1,5 +1,8 @@ -using exercise.webapi.Models; +using exercise.webapi.DTO; +using exercise.webapi.Models; using exercise.webapi.Repository; +using exercise.webapi.ViewModel; +using Microsoft.EntityFrameworkCore.Update.Internal; using static System.Reflection.Metadata.BlobBuilder; namespace exercise.webapi.Endpoints @@ -9,6 +12,10 @@ public static class BookApi public static void ConfigureBooksApi(this WebApplication app) { app.MapGet("/books", GetBooks); + app.MapGet("/book", Get); + app.MapGet("/update", UpdateAuthor); + app.MapGet("/delete", DeleteBook); + app.MapGet("/create", CreateBook); } private static async Task GetBooks(IBookRepository bookRepository) @@ -16,5 +23,50 @@ private static async Task GetBooks(IBookRepository bookRepository) var books = await bookRepository.GetAllBooks(); return TypedResults.Ok(books); } + public static async Task Get(IBookRepository repo, int id) + { + var book = await repo.GetBook(id); + return TypedResults.Ok(book); + } + + public static async Task UpdateAuthor(IBookRepository repository, int bookid, int authorid) + { + try + { + await repository.Update(bookid, authorid); + var book = repository.GetBook(bookid); + + return TypedResults.Ok(book); + } + catch (Exception ex) + { + return TypedResults.NotFound(ex); + } + + } + public static async Task DeleteBook(IBookRepository repo, int bookid) + { + try + { + repo.Delete(bookid); + return TypedResults.Ok(); + } + catch (Exception ex) + { + return TypedResults.NotFound(ex); + } + + } + public static async Task CreateBook(IBookRepository repo, string title, int authorid) + { + try + { + return TypedResults.Ok(await repo.CreateBook(title, authorid)); + } + catch (Exception ex) + { + return TypedResults.NotFound(ex); + } + } } } diff --git a/exercise.webapi/Models/Author.cs b/exercise.webapi/Models/Author.cs index 9f47878..597b87f 100644 --- a/exercise.webapi/Models/Author.cs +++ b/exercise.webapi/Models/Author.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using exercise.webapi.DTO; namespace exercise.webapi.Models { @@ -11,5 +12,6 @@ public class Author [JsonIgnore] // Todo: replace this with DTO approach public ICollection Books { get; set; } = new List(); + } } diff --git a/exercise.webapi/Program.cs b/exercise.webapi/Program.cs index 43dec56..6466031 100644 --- a/exercise.webapi/Program.cs +++ b/exercise.webapi/Program.cs @@ -12,6 +12,7 @@ builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("Library")); builder.Services.AddScoped(); + var app = builder.Build(); using (var dbContext = new DataContext(new DbContextOptions())) @@ -29,4 +30,5 @@ app.UseHttpsRedirection(); app.ConfigureBooksApi(); +app.ConfigureAuthorApi(); app.Run(); diff --git a/exercise.webapi/Repository/BookRepository.cs b/exercise.webapi/Repository/BookRepository.cs index 1f5e64a..0052168 100644 --- a/exercise.webapi/Repository/BookRepository.cs +++ b/exercise.webapi/Repository/BookRepository.cs @@ -1,6 +1,15 @@ -using exercise.webapi.Data; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using exercise.webapi.Data; +using exercise.webapi.DTO; using exercise.webapi.Models; +using exercise.webapi.ViewModel; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking; +using static System.Reflection.Metadata.BlobBuilder; namespace exercise.webapi.Repository { @@ -13,10 +22,110 @@ public BookRepository(DataContext db) _db = db; } - public async Task> GetAllBooks() + public async Task> GetAllBooks() { - return await _db.Books.Include(b => b.Author).ToListAsync(); + + var books = await _db.Books.Include(b => b.Author).ToListAsync(); + List booksDto = new List(); + books.ForEach(book => booksDto.Add(new BookDto(book))); + return booksDto; + } + public async Task GetBook(int id) + { + try + { + return new BookDto(await _db.Books.Include(b => b.Author).FirstOrDefaultAsync(book => book.Id == id)); + } + catch (Exception ex) + { + Results.BadRequest(ex); + } + return null; + + } + public async Task Update(int bookid, int authorId ) + { + var book = await _db.Books.FirstOrDefaultAsync(book => book.Id == bookid); + try + { + book.Author = await _db.Authors.FirstOrDefaultAsync(author => author.Id == authorId); + if(book.Author != null) + { + await _db.SaveChangesAsync(); + return await GetBook(bookid); + } + } + catch (Exception ex) { Results.BadRequest( ex); } + return null; + } + public async Task Delete(int bookid) + { + try + { + var book = _db.Books.FirstOrDefault(book => book.Id == bookid); + _db.Books.Remove(book); + await _db.SaveChangesAsync(); + return true; + } + catch (Exception ex) + { + Results.BadRequest(ex.Message); + } + return false; + } + //implement the CREATE book - it should return NotFound when author id is not valid and BadRequest when book object not valid + public async Task CreateBook(string title, int authorid) + { + try + { + var book = new Book(); + book.Title = title; + book.AuthorId = authorid; + book.Author = _db.Authors.FirstOrDefault(author => author.Id == authorid); + _db.Books.Add(book); + await _db.SaveChangesAsync(); + return new BookDto(book); + } + catch(Exception e) + { + Results.BadRequest(e.Message); + } + return null; } + public async Task> GetAllAuthors() + { + + + var authors = await _db.Authors.Include(b => b.Books).ToListAsync(); + var authorDtos = new List(); + foreach (var author in authors) + { + List books = await findBooksByAuthor(author.Id); + authorDtos.Add(new AuthorDto(author, books)); + } + return authorDtos; + } + public async Task GetAuthor(int id) + { + try + { + return new BookDto(await _db.Books.Include(b => b.Author).FirstOrDefaultAsync(book => book.Id == id)); + } + catch (Exception ex) + { + Results.BadRequest(ex); + } + return null; + + } + public async Task> findBooksByAuthor(int authorid) + { + var books = await _db.Books.Where( b => b.AuthorId == authorid).ToListAsync(); + List bookTitles = new List(); + books.ForEach(b => bookTitles.Add(b.Title)); + return bookTitles; + } + } } diff --git a/exercise.webapi/Repository/IBookRepository.cs b/exercise.webapi/Repository/IBookRepository.cs index f860016..b8a1ccb 100644 --- a/exercise.webapi/Repository/IBookRepository.cs +++ b/exercise.webapi/Repository/IBookRepository.cs @@ -1,9 +1,17 @@ -using exercise.webapi.Models; +using exercise.webapi.DTO; +using exercise.webapi.Models; namespace exercise.webapi.Repository { public interface IBookRepository { - public Task> GetAllBooks(); + public Task Delete(int bookid); + public Task> GetAllBooks(); + Task GetBook(int id); + public Task Update(int bookid, int authorId); + public Task CreateBook(string title, int authorid); + public Task> findBooksByAuthor(int authorid); + public Task GetAuthor(int id); + public Task> GetAllAuthors(); } } diff --git a/exercise.webapi/ViewModel/AuthorUpdate.cs b/exercise.webapi/ViewModel/AuthorUpdate.cs new file mode 100644 index 0000000..ad32cb7 --- /dev/null +++ b/exercise.webapi/ViewModel/AuthorUpdate.cs @@ -0,0 +1,11 @@ +namespace exercise.webapi.ViewModel +{ + public class AuthorUpdate + { + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public string Email { get; set; } + + } +}