From 930a45c58413445b36334de1de914fdfb406e617 Mon Sep 17 00:00:00 2001 From: "Georgy.Khatuncev" Date: Thu, 3 Oct 2024 14:22:21 +0500 Subject: [PATCH] Create HTTP REST API for Game Library --- Controllers/GamesController.cs | 69 +++++++++++++++++++++++++++++++++ Data/GameContext.cs | 24 ++++++++++++ GameLibrary.csproj | 13 +++++++ GameLibrary.sln | 25 ++++++++++++ Models/Game.cs | 12 ++++++ Program.cs | 49 +++++++++++++++++++++++ Repositories/GameRepository.cs | 58 +++++++++++++++++++++++++++ Repositories/IGameRepository.cs | 15 +++++++ appsettings.Development.json | 8 ++++ appsettings.json | 12 ++++++ 10 files changed, 285 insertions(+) create mode 100644 Controllers/GamesController.cs create mode 100644 Data/GameContext.cs create mode 100644 GameLibrary.csproj create mode 100644 GameLibrary.sln create mode 100644 Models/Game.cs create mode 100644 Program.cs create mode 100644 Repositories/GameRepository.cs create mode 100644 Repositories/IGameRepository.cs create mode 100644 appsettings.Development.json create mode 100644 appsettings.json diff --git a/Controllers/GamesController.cs b/Controllers/GamesController.cs new file mode 100644 index 0000000..3ea000d --- /dev/null +++ b/Controllers/GamesController.cs @@ -0,0 +1,69 @@ +using GameLibrary.Models; +using GameLibrary.Repositories; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace GameLibrary.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class GamesController : ControllerBase + { + private readonly IGameRepository _gameRepository; + + public GamesController(IGameRepository gameRepository) + { + _gameRepository = gameRepository; + } + + // GET: api/games + [HttpGet] + public async Task>> GetGames(string genre = null) + { + var games = await _gameRepository.GetAllGames(genre); + return Ok(games); + } + + // GET: api/games/{id} + [HttpGet("{id}")] + public async Task> GetGame(int id) + { + var game = await _gameRepository.GetGameById(id); + if (game == null) + { + return NotFound(); + } + return Ok(game); + } + + // POST: api/games + [HttpPost] + public async Task> CreateGame(Game game) + { + await _gameRepository.CreateGame(game); + return CreatedAtAction(nameof(GetGame), new { id = game.Id }, game); + } + + // PUT: api/games/{id} + [HttpPut("{id}")] + public async Task UpdateGame(int id, Game game) + { + if (id != game.Id) + { + return BadRequest(); + } + + await _gameRepository.UpdateGame(game); + return NoContent(); + } + + // DELETE: api/games/{id} + [HttpDelete("{id}")] + public async Task DeleteGame(int id) + { + await _gameRepository.DeleteGame(id); + return NoContent(); + } + } +} diff --git a/Data/GameContext.cs b/Data/GameContext.cs new file mode 100644 index 0000000..ac77b85 --- /dev/null +++ b/Data/GameContext.cs @@ -0,0 +1,24 @@ +using Microsoft.Extensions.Configuration; + +using Microsoft.EntityFrameworkCore; +using GameLibrary.Models; + +namespace GameLibrary.Data +{ + public class GameContext : DbContext + { + protected readonly IConfiguration Configuration; + public GameContext(IConfiguration configuration) + { + Configuration = configuration; + } + + protected override void OnConfiguring(DbContextOptionsBuilder options) + { + // connect to sqlite database + options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")); + } + + public DbSet Games { get; set; } + } +} \ No newline at end of file diff --git a/GameLibrary.csproj b/GameLibrary.csproj new file mode 100644 index 0000000..b17ddc2 --- /dev/null +++ b/GameLibrary.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + disable + + + + + + + diff --git a/GameLibrary.sln b/GameLibrary.sln new file mode 100644 index 0000000..ec67213 --- /dev/null +++ b/GameLibrary.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35312.102 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameLibrary", "GameLibrary.csproj", "{A4C8B6FE-20B5-4304-A80F-E098461F1138}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A4C8B6FE-20B5-4304-A80F-E098461F1138}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4C8B6FE-20B5-4304-A80F-E098461F1138}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4C8B6FE-20B5-4304-A80F-E098461F1138}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4C8B6FE-20B5-4304-A80F-E098461F1138}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5429A3BB-08B5-4F88-90AF-B686275A5080} + EndGlobalSection +EndGlobal diff --git a/Models/Game.cs b/Models/Game.cs new file mode 100644 index 0000000..948ab6a --- /dev/null +++ b/Models/Game.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace GameLibrary.Models +{ + public class Game + { + public int Id { get; set; } + public string Title { get; set; } + public string Developer { get; set; } + public List Genres { get; set; } + } +} \ No newline at end of file diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..1a4e453 --- /dev/null +++ b/Program.cs @@ -0,0 +1,49 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; + +using GameLibrary.Data; +using GameLibrary.Repositories; +using Microsoft.EntityFrameworkCore; + +namespace GameLibrary +{ + public class Program + { + public static void Main(string[] args) + { + var builder = WebApplication.CreateBuilder(args); + + builder.Services.AddDbContext(); + + builder.Services.AddScoped(); + + builder.Services.AddControllers(); + builder.Services.AddCors(options => + { + options.AddPolicy("AllowAllOrigins", + builder => + { + builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader(); + }); + }); + + var app = builder.Build(); + + app.UseCors("AllowAllOrigins"); + + app.UseHttpsRedirection(); + app.UseAuthorization(); + app.MapControllers(); + + using (var scope = app.Services.CreateScope()) + { + var dbContext = scope.ServiceProvider.GetRequiredService(); + dbContext.Database.EnsureCreated(); + } + + app.Run(); + } + } +} diff --git a/Repositories/GameRepository.cs b/Repositories/GameRepository.cs new file mode 100644 index 0000000..d254762 --- /dev/null +++ b/Repositories/GameRepository.cs @@ -0,0 +1,58 @@ +using GameLibrary.Data; +using GameLibrary.Models; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace GameLibrary.Repositories +{ + public class GameRepository : IGameRepository + { + private readonly GameContext _context; + + public GameRepository(GameContext context) + { + _context = context; + } + + public async Task> GetAllGames(string genre = null) + { + if (string.IsNullOrEmpty(genre)) + { + return await _context.Games.ToListAsync(); + } + + return await _context.Games + .Where(g => g.Genres.Contains(genre)) + .ToListAsync(); + } + + public async Task GetGameById(int id) + { + return await _context.Games.FindAsync(id); + } + + public async Task CreateGame(Game game) + { + _context.Games.Add(game); + await _context.SaveChangesAsync(); + } + + public async Task UpdateGame(Game game) + { + _context.Entry(game).State = EntityState.Modified; + await _context.SaveChangesAsync(); + } + + public async Task DeleteGame(int id) + { + var game = await _context.Games.FindAsync(id); + if (game != null) + { + _context.Games.Remove(game); + await _context.SaveChangesAsync(); + } + } + } +} \ No newline at end of file diff --git a/Repositories/IGameRepository.cs b/Repositories/IGameRepository.cs new file mode 100644 index 0000000..b5ed1ad --- /dev/null +++ b/Repositories/IGameRepository.cs @@ -0,0 +1,15 @@ +using GameLibrary.Models; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace GameLibrary.Repositories +{ + public interface IGameRepository + { + Task> GetAllGames(string genre = null); + Task GetGameById(int id); + Task CreateGame(Game game); + Task UpdateGame(Game game); + Task DeleteGame(int id); + } +} \ No newline at end of file diff --git a/appsettings.Development.json b/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/appsettings.json b/appsettings.json new file mode 100644 index 0000000..70223dc --- /dev/null +++ b/appsettings.json @@ -0,0 +1,12 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "Data Source=GameLibrary.db" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}