diff --git a/BookManagerApi/BookManagerApi.csproj b/BookManagerApi/BookManagerApi.csproj index ca79c74..43e5977 100644 --- a/BookManagerApi/BookManagerApi.csproj +++ b/BookManagerApi/BookManagerApi.csproj @@ -4,6 +4,7 @@ net6.0 enable enable + c38411eb-41d5-49b1-8fa7-961026824723 @@ -12,7 +13,9 @@ all + + diff --git a/BookManagerApi/Controllers/BookManagerController.cs b/BookManagerApi/Controllers/BookManagerController.cs index 0cde6b9..e95643a 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")] @@ -27,7 +27,7 @@ public ActionResult> GetBooks() public ActionResult GetBookById(long id) { var book = _bookManagementService.FindBookById(id); - return book; + return Ok(book); } // PUT: api/v1/book/5 @@ -35,15 +35,33 @@ 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] public ActionResult AddBook(Book 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/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/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/Program.cs b/BookManagerApi/Program.cs index 1829f2f..ed3f4dd 100644 --- a/BookManagerApi/Program.cs +++ b/BookManagerApi/Program.cs @@ -8,9 +8,20 @@ builder.Services.AddScoped(); builder.Services.AddControllers(); -builder.Services.AddDbContext(option => - option.UseInMemoryDatabase("BookDb")); +var connectionString = builder.Configuration.GetConnectionString("BookManagerApi"); + +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(); @@ -19,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/Services/BookManagementService.cs b/BookManagerApi/Services/BookManagementService.cs index 25fb4d4..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) @@ -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..f74b6fc 100644 --- a/BookManagerApi/Services/IBookManagementService.cs +++ b/BookManagerApi/Services/IBookManagementService.cs @@ -3,11 +3,12 @@ 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); } 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