From 52ba1116b8023dc71473dfb6c7ad9bfaaf388523 Mon Sep 17 00:00:00 2001 From: anaghakarurkar Date: Fri, 7 Oct 2022 21:53:36 +0100 Subject: [PATCH 1/5] IBookManagementService now contails new Delete method --- .../Controllers/BookManagerController.cs | 22 +++++++++++++++++-- BookManagerApi/Models/BookContext.cs | 14 ++++++------ .../Services/BookManagementService.cs | 13 ++++++++++- .../Services/IBookManagementService.cs | 2 ++ 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/BookManagerApi/Controllers/BookManagerController.cs b/BookManagerApi/Controllers/BookManagerController.cs index 0cde6b9..1c732c0 100644 --- a/BookManagerApi/Controllers/BookManagerController.cs +++ b/BookManagerApi/Controllers/BookManagerController.cs @@ -27,7 +27,10 @@ public ActionResult> GetBooks() public ActionResult GetBookById(long id) { var book = _bookManagementService.FindBookById(id); - return book; + if (book == null) + return NotFound(); + else + return Ok(book); } // PUT: api/v1/book/5 @@ -35,10 +38,25 @@ public ActionResult GetBookById(long id) [HttpPut("{id}")] public IActionResult UpdateBookById(long id, Book book) { + if (!_bookManagementService.BookExists(id)) + return NotFound(); + _bookManagementService.Update(id, book); - return NoContent(); + return Ok(); + } + + + // Delete: api/v1/book/5 + [HttpDelete("{id}")] + public IActionResult DeleteBookById(long id) + { + if (_bookManagementService.Delete(id)) + return Ok(); + else + return BadRequest(); } + // POST: api/v1/book // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 [HttpPost] diff --git a/BookManagerApi/Models/BookContext.cs b/BookManagerApi/Models/BookContext.cs index df3d8ab..8bb3d46 100644 --- a/BookManagerApi/Models/BookContext.cs +++ b/BookManagerApi/Models/BookContext.cs @@ -3,13 +3,13 @@ namespace BookManagerApi.Models { - public class BookContext : DbContext - { - public BookContext(DbContextOptions options) : base(options) - { - } + public class BookContext : DbContext + { + public BookContext(DbContextOptions options) : base(options) + { + } - public DbSet Books { get; set; } - } + public DbSet Books { get; set; } + } } diff --git a/BookManagerApi/Services/BookManagementService.cs b/BookManagerApi/Services/BookManagementService.cs index 25fb4d4..02fd679 100644 --- a/BookManagerApi/Services/BookManagementService.cs +++ b/BookManagerApi/Services/BookManagementService.cs @@ -28,7 +28,7 @@ public Book Create(Book book) public Book Update(long id, Book book) { var existingBookFound = FindBookById(id); - + existingBookFound.Title = book.Title; existingBookFound.Description = book.Description; existingBookFound.Author = book.Author; @@ -38,6 +38,17 @@ public Book Update(long id, Book book) return book; } + public bool Delete(long id) + { + var bookToBeRemoved = FindBookById(id); + if (bookToBeRemoved == null) + return false; + + _context.Remove(bookToBeRemoved); + _context.SaveChanges(); + return true; + } + public Book FindBookById(long id) { var book = _context.Books.Find(id); diff --git a/BookManagerApi/Services/IBookManagementService.cs b/BookManagerApi/Services/IBookManagementService.cs index 36a9032..7d15942 100644 --- a/BookManagerApi/Services/IBookManagementService.cs +++ b/BookManagerApi/Services/IBookManagementService.cs @@ -8,7 +8,9 @@ public interface IBookManagementService List GetAllBooks(); Book Create(Book book); Book Update(long id, Book book); + bool Delete(long id); Book FindBookById(long id); bool BookExists(long id); + } } From 44c0cc07f81a7a3a1b7f2343def8c96ac7ce6cc7 Mon Sep 17 00:00:00 2001 From: anaghakarurkar Date: Fri, 7 Oct 2022 21:59:19 +0100 Subject: [PATCH 2/5] IBookManagementService now contains new Delete method to delete a specified book. BookManagerController has new end-point Delete now. Modified This controller to handle errors. --- BookManagerApi/Controllers/BookManagerController.cs | 2 +- BookManagerApi/Services/BookManagementService.cs | 6 +++--- BookManagerApi/Services/IBookManagementService.cs | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/BookManagerApi/Controllers/BookManagerController.cs b/BookManagerApi/Controllers/BookManagerController.cs index 1c732c0..717bb91 100644 --- a/BookManagerApi/Controllers/BookManagerController.cs +++ b/BookManagerApi/Controllers/BookManagerController.cs @@ -54,11 +54,11 @@ public IActionResult DeleteBookById(long id) return Ok(); else return BadRequest(); + } // POST: api/v1/book - // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 [HttpPost] public ActionResult AddBook(Book book) { diff --git a/BookManagerApi/Services/BookManagementService.cs b/BookManagerApi/Services/BookManagementService.cs index 02fd679..d84c3ba 100644 --- a/BookManagerApi/Services/BookManagementService.cs +++ b/BookManagerApi/Services/BookManagementService.cs @@ -2,8 +2,8 @@ namespace BookManagerApi.Services { - public class BookManagementService : IBookManagementService - { + public class BookManagementService : IBookManagementService + { private readonly BookContext _context; public BookManagementService(BookContext context) @@ -28,7 +28,7 @@ public Book Create(Book book) public Book Update(long id, Book book) { var existingBookFound = FindBookById(id); - + existingBookFound.Title = book.Title; existingBookFound.Description = book.Description; existingBookFound.Author = book.Author; diff --git a/BookManagerApi/Services/IBookManagementService.cs b/BookManagerApi/Services/IBookManagementService.cs index 7d15942..f74b6fc 100644 --- a/BookManagerApi/Services/IBookManagementService.cs +++ b/BookManagerApi/Services/IBookManagementService.cs @@ -3,14 +3,13 @@ namespace BookManagerApi.Services { - public interface IBookManagementService - { + public interface IBookManagementService + { List GetAllBooks(); Book Create(Book book); Book Update(long id, Book book); bool Delete(long id); Book FindBookById(long id); bool BookExists(long id); - } } From abc91bcaa18d11a258503d18c338e5094c04f260 Mon Sep 17 00:00:00 2001 From: anaghakarurkar Date: Tue, 11 Oct 2022 17:36:53 +0100 Subject: [PATCH 3/5] Using Entity Framwork core for saving data to real MYSQL database. --- BookManagerApi/BookManagerApi.csproj | 2 + .../Controllers/BookManagerController.cs | 7 ++- .../20221011153708_InitialCreate.Designer.cs | 51 +++++++++++++++++++ .../20221011153708_InitialCreate.cs | 42 +++++++++++++++ .../Migrations/BookContextModelSnapshot.cs | 49 ++++++++++++++++++ BookManagerApi/Program.cs | 4 +- BookManagerApi/appsettings.json | 3 ++ 7 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 BookManagerApi/Migrations/20221011153708_InitialCreate.Designer.cs create mode 100644 BookManagerApi/Migrations/20221011153708_InitialCreate.cs create mode 100644 BookManagerApi/Migrations/BookContextModelSnapshot.cs diff --git a/BookManagerApi/BookManagerApi.csproj b/BookManagerApi/BookManagerApi.csproj index ca79c74..c840030 100644 --- a/BookManagerApi/BookManagerApi.csproj +++ b/BookManagerApi/BookManagerApi.csproj @@ -12,7 +12,9 @@ all + + diff --git a/BookManagerApi/Controllers/BookManagerController.cs b/BookManagerApi/Controllers/BookManagerController.cs index 717bb91..24fb9e6 100644 --- a/BookManagerApi/Controllers/BookManagerController.cs +++ b/BookManagerApi/Controllers/BookManagerController.cs @@ -1,7 +1,7 @@ using Microsoft.AspNetCore.Mvc; using BookManagerApi.Models; -using BookManagerApi.Services; - +using BookManagerApi.Services; + namespace BookManagerApi.Controllers { [Route("api/v1/book")] @@ -62,6 +62,9 @@ public IActionResult DeleteBookById(long id) [HttpPost] public ActionResult AddBook(Book book) { + if(_bookManagementService.BookExists(book.Id)) + return BadRequest(book); + _bookManagementService.Create(book); return CreatedAtAction(nameof(GetBookById), new { id = book.Id }, book); } diff --git a/BookManagerApi/Migrations/20221011153708_InitialCreate.Designer.cs b/BookManagerApi/Migrations/20221011153708_InitialCreate.Designer.cs new file mode 100644 index 0000000..ada5928 --- /dev/null +++ b/BookManagerApi/Migrations/20221011153708_InitialCreate.Designer.cs @@ -0,0 +1,51 @@ +// +using BookManagerApi.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace BookManagerApi.Migrations +{ + [DbContext(typeof(BookContext))] + [Migration("20221011153708_InitialCreate")] + partial class InitialCreate + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("BookManagerApi.Models.Book", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Author") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Genre") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Books"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BookManagerApi/Migrations/20221011153708_InitialCreate.cs b/BookManagerApi/Migrations/20221011153708_InitialCreate.cs new file mode 100644 index 0000000..e578cca --- /dev/null +++ b/BookManagerApi/Migrations/20221011153708_InitialCreate.cs @@ -0,0 +1,42 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BookManagerApi.Migrations +{ + public partial class InitialCreate : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterDatabase() + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Books", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Title = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Author = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Genre = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Books", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Books"); + } + } +} diff --git a/BookManagerApi/Migrations/BookContextModelSnapshot.cs b/BookManagerApi/Migrations/BookContextModelSnapshot.cs new file mode 100644 index 0000000..0e26e63 --- /dev/null +++ b/BookManagerApi/Migrations/BookContextModelSnapshot.cs @@ -0,0 +1,49 @@ +// +using BookManagerApi.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace BookManagerApi.Migrations +{ + [DbContext(typeof(BookContext))] + partial class BookContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("BookManagerApi.Models.Book", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Author") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Genre") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Books"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BookManagerApi/Program.cs b/BookManagerApi/Program.cs index 1829f2f..1ab7df9 100644 --- a/BookManagerApi/Program.cs +++ b/BookManagerApi/Program.cs @@ -8,8 +8,10 @@ builder.Services.AddScoped(); builder.Services.AddControllers(); + +var connectionString = builder.Configuration.GetConnectionString("BookManagerApi"); builder.Services.AddDbContext(option => - option.UseInMemoryDatabase("BookDb")); + option.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))); // Configure Swagger/OpenAPI Documentation // You can learn more on this link: https://aka.ms/aspnetcore/swashbuckle diff --git a/BookManagerApi/appsettings.json b/BookManagerApi/appsettings.json index af0538f..d90c9c4 100644 --- a/BookManagerApi/appsettings.json +++ b/BookManagerApi/appsettings.json @@ -5,6 +5,9 @@ "Microsoft.AspNetCore": "Warning" } }, + "ConnectionStrings": { + "BookManagerApi": "server=localhost; database=bookshop; user=bookmanagerapi; password=apiuser123" + }, "AllowedHosts": "*" } From 6df41828dc48c517c800eeb2fd2aae334a6e0c4e Mon Sep 17 00:00:00 2001 From: anaghakarurkar Date: Wed, 13 Dec 2023 17:14:51 +0000 Subject: [PATCH 4/5] Fixed bugs --- BookManagerApi/BookManagerApi.csproj | 1 + .../Controllers/BookManagerController.cs | 6 ++-- BookManagerApi/Program.cs | 15 ++++++++-- BookManagerApi/Properties/launchSettings.json | 30 ++++++++++++------- BookManagerApi/appsettings.Development.json | 3 ++ BookManagerApi/appsettings.Testing.json | 5 ++++ BookManagerApi/appsettings.json | 3 -- 7 files changed, 43 insertions(+), 20 deletions(-) create mode 100644 BookManagerApi/appsettings.Testing.json diff --git a/BookManagerApi/BookManagerApi.csproj b/BookManagerApi/BookManagerApi.csproj index c840030..43e5977 100644 --- a/BookManagerApi/BookManagerApi.csproj +++ b/BookManagerApi/BookManagerApi.csproj @@ -4,6 +4,7 @@ net6.0 enable enable + c38411eb-41d5-49b1-8fa7-961026824723 diff --git a/BookManagerApi/Controllers/BookManagerController.cs b/BookManagerApi/Controllers/BookManagerController.cs index 24fb9e6..39df982 100644 --- a/BookManagerApi/Controllers/BookManagerController.cs +++ b/BookManagerApi/Controllers/BookManagerController.cs @@ -62,9 +62,9 @@ public IActionResult DeleteBookById(long id) [HttpPost] public ActionResult AddBook(Book book) { - if(_bookManagementService.BookExists(book.Id)) - return BadRequest(book); - + //if(_bookManagementService.BookExists(book.Id)) + // return BadRequest(book); + book.Id = 0; _bookManagementService.Create(book); return CreatedAtAction(nameof(GetBookById), new { id = book.Id }, book); } diff --git a/BookManagerApi/Program.cs b/BookManagerApi/Program.cs index 1ab7df9..ed3f4dd 100644 --- a/BookManagerApi/Program.cs +++ b/BookManagerApi/Program.cs @@ -10,9 +10,18 @@ builder.Services.AddControllers(); var connectionString = builder.Configuration.GetConnectionString("BookManagerApi"); -builder.Services.AddDbContext(option => - option.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))); +if (builder.Environment.EnvironmentName == "Testing") +{ + // in test environment use a fresh in-memory DB + builder.Services.AddDbContext(option => + option.UseInMemoryDatabase("BookDb")); +} +else +{ + builder.Services.AddDbContext(option => + option.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))); +} // Configure Swagger/OpenAPI Documentation // You can learn more on this link: https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); @@ -21,7 +30,7 @@ var app = builder.Build(); // Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) +if (app.Environment.IsDevelopment() || app.Environment.EnvironmentName == "Testing") { app.UseSwagger(); app.UseSwaggerUI(); diff --git a/BookManagerApi/Properties/launchSettings.json b/BookManagerApi/Properties/launchSettings.json index 0b6f871..eab0cf7 100644 --- a/BookManagerApi/Properties/launchSettings.json +++ b/BookManagerApi/Properties/launchSettings.json @@ -1,4 +1,4 @@ -{ +{ "$schema": "https://json.schemastore.org/launchsettings.json", "iisSettings": { "windowsAuthentication": false, @@ -9,25 +9,33 @@ } }, "profiles": { - "BookManagerApi": { - "commandName": "Project", - "dotnetRunMessages": true, + "IIS Express": { + "commandName": "IISExpress", "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "https://localhost:7230;http://localhost:5213", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, - "IIS Express": { - "commandName": "IISExpress", + "Development": { + "commandName": "Project", "launchBrowser": true, "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "applicationUrl": "https://localhost:7230;http://localhost:5213", + "dotnetRunMessages": true + }, + "Testing": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Testing" + }, + "applicationUrl": "https://localhost:7230;http://localhost:5213", + "dotnetRunMessages": true } } -} - - +} \ No newline at end of file diff --git a/BookManagerApi/appsettings.Development.json b/BookManagerApi/appsettings.Development.json index ce16a2e..a021315 100644 --- a/BookManagerApi/appsettings.Development.json +++ b/BookManagerApi/appsettings.Development.json @@ -4,6 +4,9 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning" } + }, + "ConnectionStrings": { + "BookManagerApi": "server=localhost; database=bookshop; user=bookmanagerapi; password=apiuser123" } } diff --git a/BookManagerApi/appsettings.Testing.json b/BookManagerApi/appsettings.Testing.json new file mode 100644 index 0000000..ba719e5 --- /dev/null +++ b/BookManagerApi/appsettings.Testing.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=_CHANGE_ME;Trusted_Connection=True;MultipleActiveResultSets=true" + } +} \ No newline at end of file diff --git a/BookManagerApi/appsettings.json b/BookManagerApi/appsettings.json index d90c9c4..af0538f 100644 --- a/BookManagerApi/appsettings.json +++ b/BookManagerApi/appsettings.json @@ -5,9 +5,6 @@ "Microsoft.AspNetCore": "Warning" } }, - "ConnectionStrings": { - "BookManagerApi": "server=localhost; database=bookshop; user=bookmanagerapi; password=apiuser123" - }, "AllowedHosts": "*" } From 0bed96ef287e4fcb3a236f340638eb43eda41a3b Mon Sep 17 00:00:00 2001 From: anaghakarurkar Date: Wed, 13 Dec 2023 17:20:55 +0000 Subject: [PATCH 5/5] Done code refactoring --- BookManagerApi/Controllers/BookManagerController.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/BookManagerApi/Controllers/BookManagerController.cs b/BookManagerApi/Controllers/BookManagerController.cs index 39df982..e95643a 100644 --- a/BookManagerApi/Controllers/BookManagerController.cs +++ b/BookManagerApi/Controllers/BookManagerController.cs @@ -27,10 +27,7 @@ public ActionResult> GetBooks() public ActionResult GetBookById(long id) { var book = _bookManagementService.FindBookById(id); - if (book == null) - return NotFound(); - else - return Ok(book); + return Ok(book); } // PUT: api/v1/book/5