From 42bca48742edc1ed5a1ae332185b6e992155acf4 Mon Sep 17 00:00:00 2001 From: luxick Date: Fri, 13 Mar 2020 20:16:53 +0100 Subject: [PATCH] Add code generation. Replaces the client and server controller implementations with generated code from the shared project. --- EstusShots.Client/EstusShots.Client.csproj | 13 ++ EstusShots.Client/EstusShotsClient.cs | 18 +-- EstusShots.Client/Routes.cs | 141 ++++++++++++++++ EstusShots.Client/Routes.tt | 91 +++++++++++ EstusShots.Client/Routes/Drinks.cs | 34 ---- EstusShots.Client/Routes/Enemies.cs | 33 ---- EstusShots.Client/Routes/Episodes.cs | 30 ---- EstusShots.Client/Routes/Players.cs | 32 ---- EstusShots.Client/Routes/Seasons.cs | 30 ---- EstusShots.Gtk/MainWindow.cs | 1 - .../Controllers/BaseController.cs | 45 ++++++ EstusShots.Server/Controllers/Controllers.cs | 152 ++++++++++++++++++ EstusShots.Server/Controllers/Controllers.tt | 71 ++++++++ .../Controllers/DrinksController.cs | 54 ------- .../Controllers/EnemiesController.cs | 58 ------- .../Controllers/EpisodesController.cs | 70 -------- .../Controllers/PlayersController.cs | 61 ------- .../Controllers/SeasonsController.cs | 71 -------- EstusShots.Server/EstusShots.Server.csproj | 13 ++ EstusShots.Server/Services/DrinksService.cs | 1 + EstusShots.Server/Services/EnemiesService.cs | 1 + EstusShots.Server/Services/EpisodesService.cs | 1 + EstusShots.Server/Services/PlayersService.cs | 3 +- EstusShots.Server/Services/SeasonsService.cs | 1 + .../{ => Controllers}/IDrinksController.cs | 2 +- .../{ => Controllers}/IEnemiesController.cs | 2 +- .../{ => Controllers}/IEpisodesController.cs | 2 +- .../{ => Controllers}/IPlayersController.cs | 8 +- .../{ => Controllers}/ISeasonsController.cs | 2 +- 29 files changed, 542 insertions(+), 499 deletions(-) create mode 100644 EstusShots.Client/Routes.cs create mode 100644 EstusShots.Client/Routes.tt delete mode 100644 EstusShots.Client/Routes/Drinks.cs delete mode 100644 EstusShots.Client/Routes/Enemies.cs delete mode 100644 EstusShots.Client/Routes/Episodes.cs delete mode 100644 EstusShots.Client/Routes/Players.cs delete mode 100644 EstusShots.Client/Routes/Seasons.cs create mode 100644 EstusShots.Server/Controllers/BaseController.cs create mode 100644 EstusShots.Server/Controllers/Controllers.cs create mode 100644 EstusShots.Server/Controllers/Controllers.tt delete mode 100644 EstusShots.Server/Controllers/DrinksController.cs delete mode 100644 EstusShots.Server/Controllers/EnemiesController.cs delete mode 100644 EstusShots.Server/Controllers/EpisodesController.cs delete mode 100644 EstusShots.Server/Controllers/PlayersController.cs delete mode 100644 EstusShots.Server/Controllers/SeasonsController.cs rename EstusShots.Shared/Interfaces/{ => Controllers}/IDrinksController.cs (96%) rename EstusShots.Shared/Interfaces/{ => Controllers}/IEnemiesController.cs (97%) rename EstusShots.Shared/Interfaces/{ => Controllers}/IEpisodesController.cs (95%) rename EstusShots.Shared/Interfaces/{ => Controllers}/IPlayersController.cs (84%) rename EstusShots.Shared/Interfaces/{ => Controllers}/ISeasonsController.cs (93%) diff --git a/EstusShots.Client/EstusShots.Client.csproj b/EstusShots.Client/EstusShots.Client.csproj index d130a6f..1484e6d 100644 --- a/EstusShots.Client/EstusShots.Client.csproj +++ b/EstusShots.Client/EstusShots.Client.csproj @@ -12,4 +12,17 @@ + + + TextTemplatingFileGenerator + Routes.cs + + + + + + Routes.tt + + + diff --git a/EstusShots.Client/EstusShotsClient.cs b/EstusShots.Client/EstusShotsClient.cs index bf6f58a..912785c 100644 --- a/EstusShots.Client/EstusShotsClient.cs +++ b/EstusShots.Client/EstusShotsClient.cs @@ -3,14 +3,12 @@ using System.Net.Http; using System.Text; using System.Text.Json; using System.Threading.Tasks; -using EstusShots.Client.Routes; -using EstusShots.Shared.Dto; using EstusShots.Shared.Interfaces; using EstusShots.Shared.Models; namespace EstusShots.Client { - public class EstusShotsClient + public partial class EstusShotsClient { private readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions { @@ -20,13 +18,6 @@ namespace EstusShots.Client public string ApiUrl { get; } - // API Routes - public Seasons Seasons { get; } - public Episodes Episodes { get; } - public Players Players { get; } - public Drinks Drinks { get; } - public Enemies Enemies { get; } - /// /// Creates a new instance of /// @@ -35,12 +26,7 @@ namespace EstusShots.Client { ApiUrl = apiUrl; HttpClient = new HttpClient {Timeout = TimeSpan.FromSeconds(10)}; - - Seasons = new Seasons(this); - Episodes = new Episodes(this); - Players = new Players(this); - Drinks = new Drinks(this); - Enemies = new Enemies(this); + CreateApiRoutes(); } /// diff --git a/EstusShots.Client/Routes.cs b/EstusShots.Client/Routes.cs new file mode 100644 index 0000000..fdce5b8 --- /dev/null +++ b/EstusShots.Client/Routes.cs @@ -0,0 +1,141 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ +using System.Threading.Tasks; +using EstusShots.Shared.Models; +using EstusShots.Shared.Models.Parameters; +using EstusShots.Shared.Interfaces.Controllers; + +namespace EstusShots.Client +{ + // Generated part of the client class + public partial class EstusShotsClient + { + public Drinks Drinks { get; internal set; } + public Enemies Enemies { get; internal set; } + public Episodes Episodes { get; internal set; } + public Players Players { get; internal set; } + public Seasons Seasons { get; internal set; } + + private void CreateApiRoutes() + { + Drinks = new Drinks(this); + Enemies = new Enemies(this); + Episodes = new Episodes(this); + Players = new Players(this); + Seasons = new Seasons(this); + } + } + + public class Drinks : IDrinksController + { + private readonly EstusShotsClient _client; + + public Drinks(EstusShotsClient client) + { + _client = client; + } + + public async Task> GetDrinks(GetDrinksParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Drinks/GetDrinks", parameter); + + public async Task> GetDrinkDetails(GetDrinkDetailsParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Drinks/GetDrinkDetails", parameter); + + public async Task> SaveDrink(SaveDrinkParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Drinks/SaveDrink", parameter); + + } + + public class Enemies : IEnemiesController + { + private readonly EstusShotsClient _client; + + public Enemies(EstusShotsClient client) + { + _client = client; + } + + public async Task> GetEnemies(GetEnemiesParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Enemies/GetEnemies", parameter); + + public async Task> GetEnemy(GetEnemyParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Enemies/GetEnemy", parameter); + + public async Task> SaveEnemy(SaveEnemyParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Enemies/SaveEnemy", parameter); + + public async Task> DeleteEnemy(DeleteEnemyParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Enemies/DeleteEnemy", parameter); + + } + + public class Episodes : IEpisodesController + { + private readonly EstusShotsClient _client; + + public Episodes(EstusShotsClient client) + { + _client = client; + } + + public async Task> GetEpisodes(GetEpisodesParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Episodes/GetEpisodes", parameter); + + public async Task> GetEpisode(GetEpisodeParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Episodes/GetEpisode", parameter); + + public async Task> SaveEpisode(SaveEpisodeParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Episodes/SaveEpisode", parameter); + + } + + public class Players : IPlayersController + { + private readonly EstusShotsClient _client; + + public Players(EstusShotsClient client) + { + _client = client; + } + + public async Task> GetPlayers(GetPlayersParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Players/GetPlayers", parameter); + + public async Task> GetPlayerDetails(GetPlayerDetailsParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Players/GetPlayerDetails", parameter); + + public async Task> SavePlayer(SavePlayerParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Players/SavePlayer", parameter); + + public async Task> DeletePlayer(DeletePlayerParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Players/DeletePlayer", parameter); + + } + + public class Seasons : ISeasonsController + { + private readonly EstusShotsClient _client; + + public Seasons(EstusShotsClient client) + { + _client = client; + } + + public async Task> GetSeasons(GetSeasonsParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Seasons/GetSeasons", parameter); + + public async Task> GetSeason(GetSeasonParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Seasons/GetSeason", parameter); + + public async Task> SaveSeason(SaveSeasonParameter parameter) + => await _client.PostToApi($"{_client.ApiUrl}Seasons/SaveSeason", parameter); + + } + +} \ No newline at end of file diff --git a/EstusShots.Client/Routes.tt b/EstusShots.Client/Routes.tt new file mode 100644 index 0000000..237845b --- /dev/null +++ b/EstusShots.Client/Routes.tt @@ -0,0 +1,91 @@ +<#@ template language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="System.Core" #> +<#@ assembly name="$(SolutionDir)EstusShots.Shared/bin/Debug/netcoreapp3.1/EstusShots.Shared.dll" #> +<#@ import namespace="Shared.Interfaces" #> +<#@ import namespace="System.Linq" #> +<# + var assembly = typeof(IApiParameter).Assembly; + var types = assembly.GetTypes() + .Where(t => t.Namespace?.StartsWith("EstusShots.Shared") == true) + .ToArray(); + var controllers = types + .Where(t => t.Namespace == "EstusShots.Shared.Interfaces.Controllers") + .ToArray(); +#> +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ +using System.Threading.Tasks; +using EstusShots.Shared.Models; +using EstusShots.Shared.Models.Parameters; +using EstusShots.Shared.Interfaces.Controllers; + +namespace EstusShots.Client +{ + // Generated part of the client class + public partial class EstusShotsClient + { +<# + // Create API client route properties + foreach (var iFace in controllers) + { + var className = iFace.Name.Substring(1).Replace("Controller", ""); +#> + public <#=className#> <#=className#> { get; internal set; } +<# + } +#> + + private void CreateApiRoutes() + { +<# + // Instantiate API client routes + foreach (var iFace in controllers) + { + var className = iFace.Name.Substring(1).Replace("Controller", ""); +#> + <#=className#> = new <#=className#>(this); +<# + } +#> + } + } + +<# + foreach (var iFace in controllers) + { + var className = iFace.Name.Substring(1).Replace("Controller", ""); +#> + public class <#=className#> : <#=iFace.Name #> + { + private readonly EstusShotsClient _client; + + public <#=className#>(EstusShotsClient client) + { + _client = client; + } + +<# + foreach (var member in iFace.GetMembers()) + { + var responseName = $"{member.Name}Response"; + var parameterName = $"{member.Name}Parameter"; +#> + public async Task>> <#=member.Name#>(<#=parameterName#> parameter) + => await _client.PostToApi<<#=responseName#>, <#=parameterName#>>($"{_client.ApiUrl}<#=className#>/<#=member.Name#>", parameter); + +<# + } +#> + } + +<# + } +#> +} \ No newline at end of file diff --git a/EstusShots.Client/Routes/Drinks.cs b/EstusShots.Client/Routes/Drinks.cs deleted file mode 100644 index 5b06d11..0000000 --- a/EstusShots.Client/Routes/Drinks.cs +++ /dev/null @@ -1,34 +0,0 @@ -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 Drinks : IDrinksController - { - private readonly EstusShotsClient _client; - - public Drinks(EstusShotsClient client) - { - _client = client; - } - - private string ActionUrl([CallerMemberName]string caller = "") => - $"{_client.ApiUrl}{GetType().Name}/{caller}"; - - /// - public async Task> GetDrinks(GetDrinksParameter parameter) - => await _client.PostToApi(ActionUrl(), parameter); - - /// - public async Task> GetDrinkDetails(GetDrinkDetailsParameter parameter) - => await _client.PostToApi(ActionUrl(), parameter); - - /// - public async Task> SaveDrink(SaveDrinkParameter parameter) - => await _client.PostToApi(ActionUrl(), parameter); - } -} \ No newline at end of file diff --git a/EstusShots.Client/Routes/Enemies.cs b/EstusShots.Client/Routes/Enemies.cs deleted file mode 100644 index 3360e95..0000000 --- a/EstusShots.Client/Routes/Enemies.cs +++ /dev/null @@ -1,33 +0,0 @@ -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 Enemies : IEnemiesController - { - private readonly EstusShotsClient _client; - - public Enemies(EstusShotsClient client) - { - _client = client; - } - - public async Task> GetEnemies(GetEnemiesParameter parameter) - => await _client.PostToApi(ActionUrl(), parameter); - - public async Task> GetEnemy(GetEnemyParameter parameter) - => await _client.PostToApi(ActionUrl(), parameter); - - public async Task> SaveEnemy(SaveEnemyParameter parameter) - => await _client.PostToApi(ActionUrl(), parameter); - - public async Task> DeleteEnemy(DeleteEnemyParameter parameter) - => await _client.PostToApi(ActionUrl(), parameter); - - private string ActionUrl([CallerMemberName]string caller = "") => - $"{_client.ApiUrl}{GetType().Name}/{caller}"; - } -} \ No newline at end of file diff --git a/EstusShots.Client/Routes/Episodes.cs b/EstusShots.Client/Routes/Episodes.cs deleted file mode 100644 index 3d1db78..0000000 --- a/EstusShots.Client/Routes/Episodes.cs +++ /dev/null @@ -1,30 +0,0 @@ -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 Episodes : IEpisodesController - { - private readonly EstusShotsClient _client; - - public Episodes(EstusShotsClient client) - { - _client = client; - } - - private string ActionUrl([CallerMemberName]string caller = "") => - $"{_client.ApiUrl}{nameof(Episodes)}/{caller}"; - - public async Task> GetEpisodes(GetEpisodesParameter parameter) => - await _client.PostToApi(ActionUrl(), parameter); - - public async Task> GetEpisode(GetEpisodeParameter parameter) => - await _client.PostToApi(ActionUrl(), parameter); - - public async Task> SaveEpisode(SaveEpisodeParameter parameter) => - await _client.PostToApi(ActionUrl(), parameter); - } -} \ No newline at end of file diff --git a/EstusShots.Client/Routes/Players.cs b/EstusShots.Client/Routes/Players.cs deleted file mode 100644 index de2bfde..0000000 --- a/EstusShots.Client/Routes/Players.cs +++ /dev/null @@ -1,32 +0,0 @@ -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.Client/Routes/Seasons.cs b/EstusShots.Client/Routes/Seasons.cs deleted file mode 100644 index 51be399..0000000 --- a/EstusShots.Client/Routes/Seasons.cs +++ /dev/null @@ -1,30 +0,0 @@ -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 Seasons : ISeasonsController - { - private readonly EstusShotsClient _client; - - public Seasons(EstusShotsClient client) - { - _client = client; - } - - private string ActionUrl([CallerMemberName]string caller = "") => - $"{_client.ApiUrl}{nameof(Seasons)}/{caller}"; - - public async Task> GetSeasons(GetSeasonsParameter parameter) => - await _client.PostToApi(ActionUrl(), parameter); - - public async Task> GetSeason(GetSeasonParameter parameter) => - await _client.PostToApi(ActionUrl(), parameter); - - public async Task> SaveSeason(SaveSeasonParameter parameter)=> - await _client.PostToApi(ActionUrl(), parameter); - } -} \ No newline at end of file diff --git a/EstusShots.Gtk/MainWindow.cs b/EstusShots.Gtk/MainWindow.cs index 4579efd..b35e419 100644 --- a/EstusShots.Gtk/MainWindow.cs +++ b/EstusShots.Gtk/MainWindow.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using EstusShots.Client; using EstusShots.Gtk.Dialogs; using Gdk; diff --git a/EstusShots.Server/Controllers/BaseController.cs b/EstusShots.Server/Controllers/BaseController.cs new file mode 100644 index 0000000..d7ebec1 --- /dev/null +++ b/EstusShots.Server/Controllers/BaseController.cs @@ -0,0 +1,45 @@ +using System; +using System.Threading.Tasks; +using EstusShots.Shared.Interfaces; +using EstusShots.Shared.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace EstusShots.Server.Controllers +{ + /// + /// Base class for all API controllers. + /// Contains shared methods and properties that get used by the generated code. + /// + public abstract class BaseController : ControllerBase + { + private readonly ILogger _logger; + + protected BaseController(ILogger logger) + { + _logger = logger; + } + + /// + /// Generic method to handle the boilerplate code when calling an api service. + /// + /// Function that calls an API service + /// A response parameter that implements + /// An + protected 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)); + } + } + } +} \ No newline at end of file diff --git a/EstusShots.Server/Controllers/Controllers.cs b/EstusShots.Server/Controllers/Controllers.cs new file mode 100644 index 0000000..2eb2ad1 --- /dev/null +++ b/EstusShots.Server/Controllers/Controllers.cs @@ -0,0 +1,152 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using EstusShots.Server.Services; +using EstusShots.Shared.Models; +using EstusShots.Shared.Models.Parameters; +using EstusShots.Shared.Interfaces.Controllers; + +namespace EstusShots.Server.Controllers +{ + [ApiController] + [Route("/api/[controller]/[action]")] + public class DrinksController : BaseController, IDrinksController + { + private readonly DrinksService _service; + + public DrinksController(ILogger logger, DrinksService service) : base(logger) + { + _service = service; + } + + [HttpPost] + public async Task> GetDrinks(GetDrinksParameter parameter) + => await ServiceCall(() => _service.GetDrinks(parameter)); + + [HttpPost] + public async Task> GetDrinkDetails(GetDrinkDetailsParameter parameter) + => await ServiceCall(() => _service.GetDrinkDetails(parameter)); + + [HttpPost] + public async Task> SaveDrink(SaveDrinkParameter parameter) + => await ServiceCall(() => _service.SaveDrink(parameter)); + + } + + [ApiController] + [Route("/api/[controller]/[action]")] + public class EnemiesController : BaseController, IEnemiesController + { + private readonly EnemiesService _service; + + public EnemiesController(ILogger logger, EnemiesService service) : base(logger) + { + _service = service; + } + + [HttpPost] + public async Task> GetEnemies(GetEnemiesParameter parameter) + => await ServiceCall(() => _service.GetEnemies(parameter)); + + [HttpPost] + public async Task> GetEnemy(GetEnemyParameter parameter) + => await ServiceCall(() => _service.GetEnemy(parameter)); + + [HttpPost] + public async Task> SaveEnemy(SaveEnemyParameter parameter) + => await ServiceCall(() => _service.SaveEnemy(parameter)); + + [HttpPost] + public async Task> DeleteEnemy(DeleteEnemyParameter parameter) + => await ServiceCall(() => _service.DeleteEnemy(parameter)); + + } + + [ApiController] + [Route("/api/[controller]/[action]")] + public class EpisodesController : BaseController, IEpisodesController + { + private readonly EpisodesService _service; + + public EpisodesController(ILogger logger, EpisodesService service) : base(logger) + { + _service = service; + } + + [HttpPost] + public async Task> GetEpisodes(GetEpisodesParameter parameter) + => await ServiceCall(() => _service.GetEpisodes(parameter)); + + [HttpPost] + public async Task> GetEpisode(GetEpisodeParameter parameter) + => await ServiceCall(() => _service.GetEpisode(parameter)); + + [HttpPost] + public async Task> SaveEpisode(SaveEpisodeParameter parameter) + => await ServiceCall(() => _service.SaveEpisode(parameter)); + + } + + [ApiController] + [Route("/api/[controller]/[action]")] + public class PlayersController : BaseController, IPlayersController + { + private readonly PlayersService _service; + + public PlayersController(ILogger logger, PlayersService service) : base(logger) + { + _service = service; + } + + [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> DeletePlayer(DeletePlayerParameter parameter) + => await ServiceCall(() => _service.DeletePlayer(parameter)); + + } + + [ApiController] + [Route("/api/[controller]/[action]")] + public class SeasonsController : BaseController, ISeasonsController + { + private readonly SeasonsService _service; + + public SeasonsController(ILogger logger, SeasonsService service) : base(logger) + { + _service = service; + } + + [HttpPost] + public async Task> GetSeasons(GetSeasonsParameter parameter) + => await ServiceCall(() => _service.GetSeasons(parameter)); + + [HttpPost] + public async Task> GetSeason(GetSeasonParameter parameter) + => await ServiceCall(() => _service.GetSeason(parameter)); + + [HttpPost] + public async Task> SaveSeason(SaveSeasonParameter parameter) + => await ServiceCall(() => _service.SaveSeason(parameter)); + + } + +} \ No newline at end of file diff --git a/EstusShots.Server/Controllers/Controllers.tt b/EstusShots.Server/Controllers/Controllers.tt new file mode 100644 index 0000000..741ed6a --- /dev/null +++ b/EstusShots.Server/Controllers/Controllers.tt @@ -0,0 +1,71 @@ +<#@ template language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="System.Core" #> +<#@ assembly name="$(SolutionDir)EstusShots.Shared/bin/Debug/netcoreapp3.1/EstusShots.Shared.dll" #> +<#@ import namespace="Shared.Interfaces" #> +<#@ import namespace="System.Linq" #> +<# + var assembly = typeof(IApiParameter).Assembly; + var types = assembly.GetTypes() + .Where(t => t.Namespace?.StartsWith("EstusShots.Shared") == true) + .ToArray(); + var controllers = types + .Where(t => t.Namespace == "EstusShots.Shared.Interfaces.Controllers") + .ToArray(); +#> +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using EstusShots.Server.Services; +using EstusShots.Shared.Models; +using EstusShots.Shared.Models.Parameters; +using EstusShots.Shared.Interfaces.Controllers; + +namespace EstusShots.Server.Controllers +{ +<# + // The Controllers + foreach (var iFace in controllers) + { + var controllerName = iFace.Name.Substring(1); + var routeName = iFace.Name.Substring(1).Replace("Controller", ""); +#> + [ApiController] + [Route("/api/[controller]/[action]")] + public class <#=controllerName#> : BaseController, <#=iFace.Name #> + { + private readonly <#=routeName#>Service _service; + + public <#=controllerName#>(ILogger<<#=controllerName#>> logger, <#=routeName#>Service service) : base(logger) + { + _service = service; + } + +<# + // The Interface Members + foreach (var member in iFace.GetMembers()) + { + var responseName = $"{member.Name}Response"; + var parameterName = $"{member.Name}Parameter"; +#> + [HttpPost] + public async Task>> <#=member.Name#>(<#=parameterName#> parameter) + => await ServiceCall(() => _service.<#=member.Name#>(parameter)); + +<# + } +#> + } + +<# + } +#> +} \ No newline at end of file diff --git a/EstusShots.Server/Controllers/DrinksController.cs b/EstusShots.Server/Controllers/DrinksController.cs deleted file mode 100644 index 54f1ba6..0000000 --- a/EstusShots.Server/Controllers/DrinksController.cs +++ /dev/null @@ -1,54 +0,0 @@ -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 DrinksController : ControllerBase, IDrinksController - { - private readonly ILogger _logger; - private readonly DrinksService _service; - - public DrinksController(ILogger logger, DrinksService drinksService) - { - _logger = logger; - _service = drinksService; - } - - [HttpPost] - public async Task> GetDrinks(GetDrinksParameter parameter) - => await ServiceCall(() => _service.GetDrinks(parameter)); - - [HttpPost] - public async Task> GetDrinkDetails(GetDrinkDetailsParameter parameter) - => await ServiceCall(() => _service.GetDrinkDetails(parameter)); - - [HttpPost] - public async Task> SaveDrink(SaveDrinkParameter parameter) - => await ServiceCall(() => _service.SaveDrink(parameter)); - - 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)); - } - } - } -} \ No newline at end of file diff --git a/EstusShots.Server/Controllers/EnemiesController.cs b/EstusShots.Server/Controllers/EnemiesController.cs deleted file mode 100644 index c5d66ae..0000000 --- a/EstusShots.Server/Controllers/EnemiesController.cs +++ /dev/null @@ -1,58 +0,0 @@ -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 EnemiesController : ControllerBase, IEnemiesController - { - private readonly EnemiesService _service; - private readonly ILogger _logger; - - public EnemiesController(EnemiesService service, ILogger logger) - { - _service = service; - _logger = logger; - } - - [HttpPost] - public async Task> GetEnemies(GetEnemiesParameter parameter) - => await ServiceCall(() => _service.GetEnemies(parameter)); - - [HttpPost] - public async Task> GetEnemy(GetEnemyParameter parameter) - => await ServiceCall(() => _service.GetEnemy(parameter)); - - [HttpPost] - public async Task> SaveEnemy(SaveEnemyParameter parameter) - => await ServiceCall(() => _service.SaveEnemy(parameter)); - - [HttpPost] - public async Task> DeleteEnemy(DeleteEnemyParameter parameter) - => await ServiceCall(() => _service.DeleteEnemy(parameter)); - - 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)); - } - } - } -} \ No newline at end of file diff --git a/EstusShots.Server/Controllers/EpisodesController.cs b/EstusShots.Server/Controllers/EpisodesController.cs deleted file mode 100644 index be2a587..0000000 --- a/EstusShots.Server/Controllers/EpisodesController.cs +++ /dev/null @@ -1,70 +0,0 @@ -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 EpisodesController : ControllerBase, IEpisodesController - { - private readonly ILogger _logger; - private readonly EpisodesService _episodesService; - - public EpisodesController(ILogger logger, EpisodesService episodesService) - { - _logger = logger; - _episodesService = episodesService; - } - - [HttpPost] - public async Task> GetEpisodes(GetEpisodesParameter parameter) - { - try - { - _logger.LogInformation($"Request received from client '{Request.HttpContext.Connection.RemoteIpAddress}'"); - return await _episodesService.GetEpisodes(parameter); - } - catch (Exception e) - { - _logger.LogError(e, "Exception Occured"); - return new ApiResponse(new OperationResult(e)); - } - } - - [HttpPost] - public async Task> GetEpisode(GetEpisodeParameter parameter) - { - try - { - _logger.LogInformation($"Request received from client '{Request.HttpContext.Connection.RemoteIpAddress}'"); - return await _episodesService.GetEpisode(parameter); - } - catch (Exception e) - { - _logger.LogError(e, "Exception Occured"); - return new ApiResponse(new OperationResult(e)); - } - } - - [HttpPost] - public async Task> SaveEpisode(SaveEpisodeParameter parameter) - { - try - { - _logger.LogInformation($"Request received from client '{Request.HttpContext.Connection.RemoteIpAddress}'"); - return await _episodesService.SaveEpisode(parameter); - } - catch (Exception e) - { - _logger.LogError(e, "Exception Occured"); - return new ApiResponse(new OperationResult(e)); - } - } - } -} \ No newline at end of file diff --git a/EstusShots.Server/Controllers/PlayersController.cs b/EstusShots.Server/Controllers/PlayersController.cs deleted file mode 100644 index 902137b..0000000 --- a/EstusShots.Server/Controllers/PlayersController.cs +++ /dev/null @@ -1,61 +0,0 @@ -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/Controllers/SeasonsController.cs b/EstusShots.Server/Controllers/SeasonsController.cs deleted file mode 100644 index 47e42fd..0000000 --- a/EstusShots.Server/Controllers/SeasonsController.cs +++ /dev/null @@ -1,71 +0,0 @@ -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 SeasonsController : ControllerBase, ISeasonsController - { - private readonly ILogger _logger; - private readonly SeasonsService _seasonsService; - - - public SeasonsController(ILogger logger, SeasonsService seasonsService) - { - _seasonsService = seasonsService; - _logger = logger; - } - - [HttpPost] - public async Task> GetSeasons(GetSeasonsParameter parameter) - { - try - { - _logger.LogInformation($"Request received from client '{Request.HttpContext.Connection.RemoteIpAddress}'"); - return await _seasonsService.GetSeasons(parameter); - } - catch (Exception e) - { - _logger.LogError(e, "Exception Occured"); - return new ApiResponse(new OperationResult(e)); - } - } - - [HttpPost] - public async Task> GetSeason(GetSeasonParameter parameter) - { - try - { - _logger.LogInformation($"Request received from client '{Request.HttpContext.Connection.RemoteIpAddress}'"); - return await _seasonsService.GetSeason(parameter); - } - catch (Exception e) - { - _logger.LogError(e, "Exception Occured"); - return new ApiResponse(new OperationResult(e)); - } - } - - [HttpPost] - public async Task> SaveSeason(SaveSeasonParameter parameter) - { - try - { - _logger.LogInformation($"Request received from client '{Request.HttpContext.Connection.RemoteIpAddress}'"); - return await _seasonsService.SaveSeason(parameter); - } - catch (Exception e) - { - _logger.LogError(e, "Exception Occured"); - return new ApiResponse(new OperationResult(e)); - } - } - } -} \ No newline at end of file diff --git a/EstusShots.Server/EstusShots.Server.csproj b/EstusShots.Server/EstusShots.Server.csproj index 93597be..3f4bd81 100644 --- a/EstusShots.Server/EstusShots.Server.csproj +++ b/EstusShots.Server/EstusShots.Server.csproj @@ -26,4 +26,17 @@ + + + + TextTemplatingFileGenerator + Controllers.cs + + + + + + Controllers.tt + + diff --git a/EstusShots.Server/Services/DrinksService.cs b/EstusShots.Server/Services/DrinksService.cs index 48f6c58..3ddb26c 100644 --- a/EstusShots.Server/Services/DrinksService.cs +++ b/EstusShots.Server/Services/DrinksService.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using AutoMapper; using EstusShots.Server.Models; using EstusShots.Shared.Interfaces; +using EstusShots.Shared.Interfaces.Controllers; using EstusShots.Shared.Models; using EstusShots.Shared.Models.Parameters; using Microsoft.EntityFrameworkCore; diff --git a/EstusShots.Server/Services/EnemiesService.cs b/EstusShots.Server/Services/EnemiesService.cs index 73cea37..ea6180e 100644 --- a/EstusShots.Server/Services/EnemiesService.cs +++ b/EstusShots.Server/Services/EnemiesService.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using AutoMapper; using EstusShots.Server.Models; using EstusShots.Shared.Interfaces; +using EstusShots.Shared.Interfaces.Controllers; using EstusShots.Shared.Models; using EstusShots.Shared.Models.Parameters; using Microsoft.EntityFrameworkCore; diff --git a/EstusShots.Server/Services/EpisodesService.cs b/EstusShots.Server/Services/EpisodesService.cs index ce11b46..f23d2a0 100644 --- a/EstusShots.Server/Services/EpisodesService.cs +++ b/EstusShots.Server/Services/EpisodesService.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using AutoMapper; using EstusShots.Server.Models; using EstusShots.Shared.Interfaces; +using EstusShots.Shared.Interfaces.Controllers; using EstusShots.Shared.Models; using EstusShots.Shared.Models.Parameters; using Microsoft.EntityFrameworkCore; diff --git a/EstusShots.Server/Services/PlayersService.cs b/EstusShots.Server/Services/PlayersService.cs index 75e5640..6689e3b 100644 --- a/EstusShots.Server/Services/PlayersService.cs +++ b/EstusShots.Server/Services/PlayersService.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using AutoMapper; using EstusShots.Server.Models; using EstusShots.Shared.Interfaces; +using EstusShots.Shared.Interfaces.Controllers; using EstusShots.Shared.Models; using EstusShots.Shared.Models.Parameters; using Microsoft.EntityFrameworkCore; @@ -65,7 +66,7 @@ namespace EstusShots.Server.Services } } - public Task> DeletePlayers(DeletePlayerParameter parameter) + public Task> DeletePlayer(DeletePlayerParameter parameter) { throw new System.NotImplementedException(); } diff --git a/EstusShots.Server/Services/SeasonsService.cs b/EstusShots.Server/Services/SeasonsService.cs index a13f6f0..449e577 100644 --- a/EstusShots.Server/Services/SeasonsService.cs +++ b/EstusShots.Server/Services/SeasonsService.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using AutoMapper; using EstusShots.Server.Models; using EstusShots.Shared.Interfaces; +using EstusShots.Shared.Interfaces.Controllers; using EstusShots.Shared.Models; using EstusShots.Shared.Models.Parameters; using Microsoft.EntityFrameworkCore; diff --git a/EstusShots.Shared/Interfaces/IDrinksController.cs b/EstusShots.Shared/Interfaces/Controllers/IDrinksController.cs similarity index 96% rename from EstusShots.Shared/Interfaces/IDrinksController.cs rename to EstusShots.Shared/Interfaces/Controllers/IDrinksController.cs index 1ac7473..3dcb5c6 100644 --- a/EstusShots.Shared/Interfaces/IDrinksController.cs +++ b/EstusShots.Shared/Interfaces/Controllers/IDrinksController.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using EstusShots.Shared.Models; using EstusShots.Shared.Models.Parameters; -namespace EstusShots.Shared.Interfaces +namespace EstusShots.Shared.Interfaces.Controllers { public interface IDrinksController { diff --git a/EstusShots.Shared/Interfaces/IEnemiesController.cs b/EstusShots.Shared/Interfaces/Controllers/IEnemiesController.cs similarity index 97% rename from EstusShots.Shared/Interfaces/IEnemiesController.cs rename to EstusShots.Shared/Interfaces/Controllers/IEnemiesController.cs index 30619e8..c7db095 100644 --- a/EstusShots.Shared/Interfaces/IEnemiesController.cs +++ b/EstusShots.Shared/Interfaces/Controllers/IEnemiesController.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using EstusShots.Shared.Models; using EstusShots.Shared.Models.Parameters; -namespace EstusShots.Shared.Interfaces +namespace EstusShots.Shared.Interfaces.Controllers { /// /// Load and manipulate Enemy objects diff --git a/EstusShots.Shared/Interfaces/IEpisodesController.cs b/EstusShots.Shared/Interfaces/Controllers/IEpisodesController.cs similarity index 95% rename from EstusShots.Shared/Interfaces/IEpisodesController.cs rename to EstusShots.Shared/Interfaces/Controllers/IEpisodesController.cs index d7e5a8c..d111ff7 100644 --- a/EstusShots.Shared/Interfaces/IEpisodesController.cs +++ b/EstusShots.Shared/Interfaces/Controllers/IEpisodesController.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using EstusShots.Shared.Models; using EstusShots.Shared.Models.Parameters; -namespace EstusShots.Shared.Interfaces +namespace EstusShots.Shared.Interfaces.Controllers { /// /// Access to episodes diff --git a/EstusShots.Shared/Interfaces/IPlayersController.cs b/EstusShots.Shared/Interfaces/Controllers/IPlayersController.cs similarity index 84% rename from EstusShots.Shared/Interfaces/IPlayersController.cs rename to EstusShots.Shared/Interfaces/Controllers/IPlayersController.cs index b88ea0d..1e34486 100644 --- a/EstusShots.Shared/Interfaces/IPlayersController.cs +++ b/EstusShots.Shared/Interfaces/Controllers/IPlayersController.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using EstusShots.Shared.Models; using EstusShots.Shared.Models.Parameters; -namespace EstusShots.Shared.Interfaces +namespace EstusShots.Shared.Interfaces.Controllers { /// /// Load and manipulate player objects @@ -33,8 +33,8 @@ namespace EstusShots.Shared.Interfaces /// /// Deletes a player /// - /// An instance - /// An ApiResponse instance of type - Task> DeletePlayers(DeletePlayerParameter parameter); + /// An instance + /// An ApiResponse instance of type + Task> DeletePlayer(DeletePlayerParameter parameter); } } \ No newline at end of file diff --git a/EstusShots.Shared/Interfaces/ISeasonsController.cs b/EstusShots.Shared/Interfaces/Controllers/ISeasonsController.cs similarity index 93% rename from EstusShots.Shared/Interfaces/ISeasonsController.cs rename to EstusShots.Shared/Interfaces/Controllers/ISeasonsController.cs index b8e7ef9..9f80cd7 100644 --- a/EstusShots.Shared/Interfaces/ISeasonsController.cs +++ b/EstusShots.Shared/Interfaces/Controllers/ISeasonsController.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using EstusShots.Shared.Models; using EstusShots.Shared.Models.Parameters; -namespace EstusShots.Shared.Interfaces +namespace EstusShots.Shared.Interfaces.Controllers { /// /// Access many seasons with one request