From 3fe1be98d8b47cf072f66eca27069cec7f68634d Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Tue, 24 Sep 2019 22:28:42 +0400 Subject: [PATCH 1/6] [backend] feat: Implement basic CRUD operations for instructors management --- Controllers/InstructorsDataController.cs | 58 ++++++++++++++++++++++++ Controllers/SampleDataController.cs | 44 ------------------ Models/DatabaseContext.cs | 12 +++++ Models/Instructor.cs | 8 ++++ Program.cs | 2 +- Properties/launchSettings.json | 2 +- Startup.cs | 21 ++++----- appsettings.json | 5 +- instructors-crud-test-task.csproj | 2 +- 9 files changed, 95 insertions(+), 59 deletions(-) create mode 100644 Controllers/InstructorsDataController.cs delete mode 100644 Controllers/SampleDataController.cs create mode 100644 Models/DatabaseContext.cs create mode 100644 Models/Instructor.cs diff --git a/Controllers/InstructorsDataController.cs b/Controllers/InstructorsDataController.cs new file mode 100644 index 0000000..a2ec1c2 --- /dev/null +++ b/Controllers/InstructorsDataController.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using InstructorsListApp.Models; + +namespace InstructorsListApp.Controllers +{ + [Route("api/v1/instructors")] + public class InstructorsDataController : Controller + { + DatabaseContext databaseContext; + + public InstructorsDataController(DatabaseContext context) + { + databaseContext = context; + } + + [HttpGet] + public IEnumerable GetAllInstructors() + { + return databaseContext.Instructors.ToList(); + } + + [HttpPost("add")] + public IActionResult CreateInstructorEntry([FromBody] Instructor instructor) { + if(ModelState.IsValid) { + instructor.Id = Guid.NewGuid().ToString(); + databaseContext.Instructors.Add(instructor); + databaseContext.SaveChangesAsync(); + return Ok(instructor.Id); + } + return BadRequest(ModelState); + } + + [HttpPut("{id}")] + public IActionResult UpdateInstructorEntry(string id, [FromBody] Instructor instructor) { + if(ModelState.IsValid) { + databaseContext.Instructors.Update(instructor); + databaseContext.SaveChangesAsync(); + return Ok(); + } + return BadRequest(ModelState); + } + + [HttpDelete("{id}")] + public IActionResult DelereInstructorEntry(string id) { + Instructor instructor = databaseContext.Instructors.FirstOrDefault(i => i.Id == id); + if(instructor != null) { + databaseContext.Instructors.Remove(instructor); + databaseContext.SaveChangesAsync(); + return Ok(); + } + return BadRequest("No such instructor"); + } + } +} diff --git a/Controllers/SampleDataController.cs b/Controllers/SampleDataController.cs deleted file mode 100644 index 3c4eef5..0000000 --- a/Controllers/SampleDataController.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; - -namespace instructors_crud_test_task.Controllers -{ - [Route("api/[controller]")] - public class SampleDataController : Controller - { - private static string[] Summaries = new[] - { - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - }; - - [HttpGet("[action]")] - public IEnumerable WeatherForecasts() - { - var rng = new Random(); - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - DateFormatted = DateTime.Now.AddDays(index).ToString("d"), - TemperatureC = rng.Next(-20, 55), - Summary = Summaries[rng.Next(Summaries.Length)] - }); - } - - public class WeatherForecast - { - public string DateFormatted { get; set; } - public int TemperatureC { get; set; } - public string Summary { get; set; } - - public int TemperatureF - { - get - { - return 32 + (int)(TemperatureC / 0.5556); - } - } - } - } -} diff --git a/Models/DatabaseContext.cs b/Models/DatabaseContext.cs new file mode 100644 index 0000000..9c6f851 --- /dev/null +++ b/Models/DatabaseContext.cs @@ -0,0 +1,12 @@ +using Microsoft.EntityFrameworkCore; + +namespace InstructorsListApp.Models { + public class DatabaseContext : DbContext + { + public DatabaseContext(DbContextOptions options) + : base(options) + { } + + public DbSet Instructors { get; set; } + } +} \ No newline at end of file diff --git a/Models/Instructor.cs b/Models/Instructor.cs new file mode 100644 index 0000000..d944063 --- /dev/null +++ b/Models/Instructor.cs @@ -0,0 +1,8 @@ +namespace InstructorsListApp.Models { + public class Instructor { + public string Id {get; set;} + public string FirstName {get;set;} + public string MiddleName {get;set;} + public string LastName {get;set;} +} +} \ No newline at end of file diff --git a/Program.cs b/Program.cs index 976c6ab..1530579 100644 --- a/Program.cs +++ b/Program.cs @@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; -namespace instructors_crud_test_task +namespace InstructorsListApp { public class Program { diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json index 234377b..8492fa0 100644 --- a/Properties/launchSettings.json +++ b/Properties/launchSettings.json @@ -15,7 +15,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" } }, - "instructors_crud_test_task": { + "InstructorsListApp": { "commandName": "Project", "launchBrowser": true, "applicationUrl": "http://localhost:5000", diff --git a/Startup.cs b/Startup.cs index 03a0434..0dd1413 100644 --- a/Startup.cs +++ b/Startup.cs @@ -1,12 +1,12 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.SpaServices.AngularCli; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using InstructorsListApp.Models; +using Microsoft.EntityFrameworkCore; -namespace instructors_crud_test_task +namespace InstructorsListApp { public class Startup { @@ -21,7 +21,13 @@ namespace instructors_crud_test_task public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); - + string conString = Microsoft + .Extensions + .Configuration + .ConfigurationExtensions + .GetConnectionString(this.Configuration, "DefaultDatabase"); + services.AddDbContext(options => options.UseSqlServer(conString)); + //services. // In production, the Angular files will be served from this directory services.AddSpaStaticFiles(configuration => { @@ -47,13 +53,6 @@ namespace instructors_crud_test_task app.UseStaticFiles(); app.UseSpaStaticFiles(); - app.UseMvc(routes => - { - routes.MapRoute( - name: "default", - template: "{controller}/{action=Index}/{id?}"); - }); - app.UseSpa(spa => { // To learn more about options for serving an Angular SPA from ASP.NET Core, diff --git a/appsettings.json b/appsettings.json index def9159..2ee124e 100644 --- a/appsettings.json +++ b/appsettings.json @@ -4,5 +4,8 @@ "Default": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "ConnectionStrings": { + "DefaultDatabase": "Server=(localdb)\\mssqllocaldb;Database=instructorsdb;Trusted_Connection=True;" + } } diff --git a/instructors-crud-test-task.csproj b/instructors-crud-test-task.csproj index 0d20f45..28f33d6 100644 --- a/instructors-crud-test-task.csproj +++ b/instructors-crud-test-task.csproj @@ -10,7 +10,7 @@ false - instructors_crud_test_task + InstructorsListApp From c9de99b9db009d6e98bd2b7cb4ab7e6eb47d912b Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Tue, 24 Sep 2019 22:37:09 +0400 Subject: [PATCH 2/6] [backend] fix: Fix build error in DatabaseContext --- Models/DatabaseContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Models/DatabaseContext.cs b/Models/DatabaseContext.cs index 9c6f851..30cd62e 100644 --- a/Models/DatabaseContext.cs +++ b/Models/DatabaseContext.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore; namespace InstructorsListApp.Models { public class DatabaseContext : DbContext { - public DatabaseContext(DbContextOptions options) + public DatabaseContext(DbContextOptions options) : base(options) { } From ee3071ab165418ea0070a5277d1bdbe61815d3c2 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Wed, 25 Sep 2019 00:23:47 +0400 Subject: [PATCH 3/6] [backend] fix: Fix route handling --- Controllers/InstructorsDataController.cs | 2 +- Startup.cs | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Controllers/InstructorsDataController.cs b/Controllers/InstructorsDataController.cs index a2ec1c2..4620a27 100644 --- a/Controllers/InstructorsDataController.cs +++ b/Controllers/InstructorsDataController.cs @@ -1,13 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using InstructorsListApp.Models; namespace InstructorsListApp.Controllers { [Route("api/v1/instructors")] + [ApiController] public class InstructorsDataController : Controller { DatabaseContext databaseContext; diff --git a/Startup.cs b/Startup.cs index 0dd1413..e4b5557 100644 --- a/Startup.cs +++ b/Startup.cs @@ -27,12 +27,13 @@ namespace InstructorsListApp .ConfigurationExtensions .GetConnectionString(this.Configuration, "DefaultDatabase"); services.AddDbContext(options => options.UseSqlServer(conString)); - //services. // In production, the Angular files will be served from this directory services.AddSpaStaticFiles(configuration => { configuration.RootPath = "ClientApp/dist"; }); + + } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -49,7 +50,14 @@ namespace InstructorsListApp app.UseHsts(); } - app.UseHttpsRedirection(); + app.UseMvc(routes => + { + routes.MapRoute( + name: "default", + template: "{controller=Home}/{action=Index}/{id?}"); + }); + + //app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseSpaStaticFiles(); From b46120ddc5cbf167df2db3c98228ff58eaa980cf Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Wed, 25 Sep 2019 00:38:13 +0400 Subject: [PATCH 4/6] [backend] fix: Slightly change name of DB --- appsettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appsettings.json b/appsettings.json index 2ee124e..299ab74 100644 --- a/appsettings.json +++ b/appsettings.json @@ -6,6 +6,6 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - "DefaultDatabase": "Server=(localdb)\\mssqllocaldb;Database=instructorsdb;Trusted_Connection=True;" + "DefaultDatabase": "Server=(localdb)\\mssqllocaldb;Database=instructorsDB;Trusted_Connection=True;" } } From 7d55a9b7a10a80795e3e4f80a746ed1eeaf76d30 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Wed, 25 Sep 2019 18:39:26 +0400 Subject: [PATCH 5/6] [backend] fix: Fix connection string to M$ SQL Server --- appsettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appsettings.json b/appsettings.json index 299ab74..2836fb4 100644 --- a/appsettings.json +++ b/appsettings.json @@ -6,6 +6,6 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - "DefaultDatabase": "Server=(localdb)\\mssqllocaldb;Database=instructorsDB;Trusted_Connection=True;" + "DefaultDatabase": "Server=localhost;Database=instructorsDB;User Id=instructorsOwner;Password=P@ssW0rd;MultipleActiveResultSets=True;" } } From 38d05d3a897ec17c12ec58339e7ee8c7ef636052 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Wed, 25 Sep 2019 18:40:52 +0400 Subject: [PATCH 6/6] [backend] fix: Fix issues with commit transaction, add "exists" condition in UpdateInstructorEntry --- Controllers/InstructorsDataController.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Controllers/InstructorsDataController.cs b/Controllers/InstructorsDataController.cs index 4620a27..f1702d8 100644 --- a/Controllers/InstructorsDataController.cs +++ b/Controllers/InstructorsDataController.cs @@ -28,7 +28,7 @@ namespace InstructorsListApp.Controllers if(ModelState.IsValid) { instructor.Id = Guid.NewGuid().ToString(); databaseContext.Instructors.Add(instructor); - databaseContext.SaveChangesAsync(); + databaseContext.SaveChanges(); return Ok(instructor.Id); } return BadRequest(ModelState); @@ -37,9 +37,15 @@ namespace InstructorsListApp.Controllers [HttpPut("{id}")] public IActionResult UpdateInstructorEntry(string id, [FromBody] Instructor instructor) { if(ModelState.IsValid) { - databaseContext.Instructors.Update(instructor); - databaseContext.SaveChangesAsync(); - return Ok(); + instructor.Id = id; + var instructorEntry = databaseContext.Instructors.FirstOrDefault(i => i.Id == id); + if(instructorEntry != null) { + databaseContext.Entry(instructorEntry).State = Microsoft.EntityFrameworkCore.EntityState.Detached; + databaseContext.Instructors.Update(instructor); + databaseContext.SaveChanges(); + return Ok(); + } + return NotFound("Given instructor isn't found"); } return BadRequest(ModelState); } @@ -49,10 +55,10 @@ namespace InstructorsListApp.Controllers Instructor instructor = databaseContext.Instructors.FirstOrDefault(i => i.Id == id); if(instructor != null) { databaseContext.Instructors.Remove(instructor); - databaseContext.SaveChangesAsync(); + databaseContext.SaveChanges(); return Ok(); } - return BadRequest("No such instructor"); + return NotFound("No such instructor"); } } }