diff --git a/EstusShots.Client/EstusShots.Client.csproj b/EstusShots.Client/EstusShots.Client.csproj index 548a249..d130a6f 100644 --- a/EstusShots.Client/EstusShots.Client.csproj +++ b/EstusShots.Client/EstusShots.Client.csproj @@ -8,4 +8,8 @@ + + + + diff --git a/EstusShots.Client/EstusShotsClient.cs b/EstusShots.Client/EstusShotsClient.cs index f5f3927..4a126fe 100644 --- a/EstusShots.Client/EstusShotsClient.cs +++ b/EstusShots.Client/EstusShotsClient.cs @@ -55,6 +55,8 @@ namespace EstusShots.Client var response = await HttpClient.PostAsync(url, content); response.EnsureSuccessStatusCode(); var json = await response.Content.ReadAsStringAsync(); + if (json.IsNullOrWhiteSpace() || json == "{}") + return new ApiResponse(new OperationResult(false, "Invalid response", "The server returned no or empty data")); var result = JsonSerializer.Deserialize>(json, _serializerOptions); return result; } diff --git a/EstusShots.Client/Routes/Players.cs b/EstusShots.Client/Routes/Players.cs new file mode 100644 index 0000000..de2bfde --- /dev/null +++ b/EstusShots.Client/Routes/Players.cs @@ -0,0 +1,32 @@ +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using EstusShots.Shared.Interfaces; +using EstusShots.Shared.Models; +using EstusShots.Shared.Models.Parameters; + +namespace EstusShots.Client.Routes +{ + public class Players : IPlayersController + { + private readonly EstusShotsClient _client; + + public Players(EstusShotsClient client) + { + _client = client; + } + private string ActionUrl([CallerMemberName]string caller = "") => + $"{_client.ApiUrl}{GetType().Name}/{caller}"; + + public async Task> GetPlayers(GetPlayersParameter parameter) + => await _client.PostToApi(ActionUrl(), parameter); + + public async Task> GetPlayerDetails(GetPlayerDetailsParameter parameter) + => await _client.PostToApi(ActionUrl(), parameter); + + public async Task> SavePlayer(SavePlayerParameter parameter) + => await _client.PostToApi(ActionUrl(), parameter); + + public async Task> DeletePlayers(DeletePlayerParameter parameter) + => await _client.PostToApi(ActionUrl(), parameter); + } +} \ No newline at end of file diff --git a/EstusShots.Server/Controllers/PlayersController.cs b/EstusShots.Server/Controllers/PlayersController.cs new file mode 100644 index 0000000..902137b --- /dev/null +++ b/EstusShots.Server/Controllers/PlayersController.cs @@ -0,0 +1,61 @@ +using System; +using System.Threading.Tasks; +using EstusShots.Server.Services; +using EstusShots.Shared.Interfaces; +using EstusShots.Shared.Models; +using EstusShots.Shared.Models.Parameters; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace EstusShots.Server.Controllers +{ + [ApiController] + [Route("/api/[controller]/[action]")] + public class PlayersController : ControllerBase, IPlayersController + { + private readonly ILogger _logger; + private readonly PlayersService _service; + + public PlayersController(ILogger logger, PlayersService service) + { + _logger = logger; + _service = service; + } + + private async Task> ServiceCall(Func>> serviceCall) + where T : class, IApiResponse, new() + { + try + { + if (!ModelState.IsValid) + { + _logger.LogError($"Model invalid"); + + } + _logger.LogInformation($"Request received from client '{Request.HttpContext.Connection.RemoteIpAddress}'"); + return await serviceCall(); + } + catch (Exception e) + { + _logger.LogError(e, "Exception Occured"); + return new ApiResponse(new OperationResult(e)); + } + } + + [HttpPost] + public async Task> GetPlayers(GetPlayersParameter parameter) + => await ServiceCall(() => _service.GetPlayers(parameter)); + + [HttpPost] + public async Task> GetPlayerDetails(GetPlayerDetailsParameter parameter) + => await ServiceCall(() => _service.GetPlayerDetails(parameter)); + + [HttpPost] + public async Task> SavePlayer(SavePlayerParameter parameter) + => await ServiceCall(() => _service.SavePlayer(parameter)); + + [HttpPost] + public async Task> DeletePlayers(DeletePlayerParameter parameter) + => await ServiceCall(() => _service.DeletePlayers(parameter)); + } +} \ No newline at end of file diff --git a/EstusShots.Server/Program.cs b/EstusShots.Server/Program.cs index db7d953..e187dd0 100644 --- a/EstusShots.Server/Program.cs +++ b/EstusShots.Server/Program.cs @@ -16,9 +16,11 @@ namespace EstusShots.Server CreateHostBuilder(args).Build().Run(); } - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) + public static IHostBuilder CreateHostBuilder(string[] args) + { + return Host.CreateDefaultBuilder(args) .ConfigureLogging(builder => { builder.AddConsole(); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); + } } } \ No newline at end of file diff --git a/EstusShots.Server/Services/PlayersService.cs b/EstusShots.Server/Services/PlayersService.cs new file mode 100644 index 0000000..8f813f0 --- /dev/null +++ b/EstusShots.Server/Services/PlayersService.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using EstusShots.Shared.Interfaces; +using EstusShots.Shared.Models; +using EstusShots.Shared.Models.Parameters; +using Microsoft.Extensions.Logging; + +namespace EstusShots.Server.Services +{ + public class PlayersService : IPlayersController + { + private readonly ILogger _logger; + + public PlayersService(ILogger logger) + { + _logger = logger; + } + + public Task> GetPlayers(GetPlayersParameter parameter) + { + throw new System.NotImplementedException(); + } + + public Task> GetPlayerDetails(GetPlayerDetailsParameter parameter) + { + throw new System.NotImplementedException(); + } + + public Task> SavePlayer(SavePlayerParameter parameter) + { + throw new System.NotImplementedException(); + } + + public Task> DeletePlayers(DeletePlayerParameter parameter) + { + throw new System.NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/EstusShots.Server/Startup.cs b/EstusShots.Server/Startup.cs index 3772acd..9af3405 100644 --- a/EstusShots.Server/Startup.cs +++ b/EstusShots.Server/Startup.cs @@ -15,7 +15,7 @@ namespace EstusShots.Server public IConfiguration Configuration { get; } private bool IsDevelopment { get; set; } - + public Startup(IConfiguration configuration) { Configuration = configuration; @@ -34,19 +34,17 @@ namespace EstusShots.Server services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; - if (IsDevelopment) - { - options.JsonSerializerOptions.WriteIndented = true; - } + if (IsDevelopment) options.JsonSerializerOptions.WriteIndented = true; }); services.AddSwaggerGen(options => { - options.SwaggerDoc("v1", new OpenApiInfo { Title = "Estus Shots API", Version = "v1" }); + options.SwaggerDoc("v1", new OpenApiInfo {Title = "Estus Shots API", Version = "v1"}); }); // Register business logic services services.AddScoped(); services.AddScoped(); + services.AddScoped(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -54,23 +52,16 @@ namespace EstusShots.Server { IsDevelopment = env.IsDevelopment(); if (IsDevelopment) - { app.UseDeveloperExceptionPage(); - } else - { app.UseHttpsRedirection(); - } // Enable middleware to serve generated Swagger as a JSON endpoint. app.UseSwagger(); // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), // specifying the Swagger JSON endpoint. - app.UseSwaggerUI(c => - { - c.SwaggerEndpoint("/swagger/v1/swagger.json", "Estus Shots API V1"); - }); + app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Estus Shots API V1"); }); app.UseRouting(); app.UseAuthorization();