Add code generation.

Replaces the client and server controller implementations with generated code from the shared project.
This commit is contained in:
2020-03-13 20:16:53 +01:00
parent 7bd44091cf
commit 42bca48742
29 changed files with 542 additions and 499 deletions

View File

@@ -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
{
/// <summary>
/// Base class for all API controllers.
/// Contains shared methods and properties that get used by the generated code.
/// </summary>
public abstract class BaseController : ControllerBase
{
private readonly ILogger _logger;
protected BaseController(ILogger logger)
{
_logger = logger;
}
/// <summary>
/// Generic method to handle the boilerplate code when calling an api service.
/// </summary>
/// <param name="serviceCall">Function that calls an API service</param>
/// <typeparam name="T">A response parameter that implements <see cref="IApiResponse"/></typeparam>
/// <returns>An <see cref="ApiResponse{T}"/></returns>
protected async Task<ApiResponse<T>> ServiceCall<T>(Func<Task<ApiResponse<T>>> 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<T>(new OperationResult(e));
}
}
}
}

View File

@@ -0,0 +1,152 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
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<DrinksController> logger, DrinksService service) : base(logger)
{
_service = service;
}
[HttpPost]
public async Task<ApiResponse<GetDrinksResponse>> GetDrinks(GetDrinksParameter parameter)
=> await ServiceCall(() => _service.GetDrinks(parameter));
[HttpPost]
public async Task<ApiResponse<GetDrinkDetailsResponse>> GetDrinkDetails(GetDrinkDetailsParameter parameter)
=> await ServiceCall(() => _service.GetDrinkDetails(parameter));
[HttpPost]
public async Task<ApiResponse<SaveDrinkResponse>> 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<EnemiesController> logger, EnemiesService service) : base(logger)
{
_service = service;
}
[HttpPost]
public async Task<ApiResponse<GetEnemiesResponse>> GetEnemies(GetEnemiesParameter parameter)
=> await ServiceCall(() => _service.GetEnemies(parameter));
[HttpPost]
public async Task<ApiResponse<GetEnemyResponse>> GetEnemy(GetEnemyParameter parameter)
=> await ServiceCall(() => _service.GetEnemy(parameter));
[HttpPost]
public async Task<ApiResponse<SaveEnemyResponse>> SaveEnemy(SaveEnemyParameter parameter)
=> await ServiceCall(() => _service.SaveEnemy(parameter));
[HttpPost]
public async Task<ApiResponse<DeleteEnemyResponse>> 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<EpisodesController> logger, EpisodesService service) : base(logger)
{
_service = service;
}
[HttpPost]
public async Task<ApiResponse<GetEpisodesResponse>> GetEpisodes(GetEpisodesParameter parameter)
=> await ServiceCall(() => _service.GetEpisodes(parameter));
[HttpPost]
public async Task<ApiResponse<GetEpisodeResponse>> GetEpisode(GetEpisodeParameter parameter)
=> await ServiceCall(() => _service.GetEpisode(parameter));
[HttpPost]
public async Task<ApiResponse<SaveEpisodeResponse>> 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<PlayersController> logger, PlayersService service) : base(logger)
{
_service = service;
}
[HttpPost]
public async Task<ApiResponse<GetPlayersResponse>> GetPlayers(GetPlayersParameter parameter)
=> await ServiceCall(() => _service.GetPlayers(parameter));
[HttpPost]
public async Task<ApiResponse<GetPlayerDetailsResponse>> GetPlayerDetails(GetPlayerDetailsParameter parameter)
=> await ServiceCall(() => _service.GetPlayerDetails(parameter));
[HttpPost]
public async Task<ApiResponse<SavePlayerResponse>> SavePlayer(SavePlayerParameter parameter)
=> await ServiceCall(() => _service.SavePlayer(parameter));
[HttpPost]
public async Task<ApiResponse<DeletePlayerResponse>> 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<SeasonsController> logger, SeasonsService service) : base(logger)
{
_service = service;
}
[HttpPost]
public async Task<ApiResponse<GetSeasonsResponse>> GetSeasons(GetSeasonsParameter parameter)
=> await ServiceCall(() => _service.GetSeasons(parameter));
[HttpPost]
public async Task<ApiResponse<GetSeasonResponse>> GetSeason(GetSeasonParameter parameter)
=> await ServiceCall(() => _service.GetSeason(parameter));
[HttpPost]
public async Task<ApiResponse<SaveSeasonResponse>> SaveSeason(SaveSeasonParameter parameter)
=> await ServiceCall(() => _service.SaveSeason(parameter));
}
}

View File

@@ -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();
#>
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
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<ApiResponse<<#=responseName#>>> <#=member.Name#>(<#=parameterName#> parameter)
=> await ServiceCall(() => _service.<#=member.Name#>(parameter));
<#
}
#>
}
<#
}
#>
}

View File

@@ -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<DrinksController> logger, DrinksService drinksService)
{
_logger = logger;
_service = drinksService;
}
[HttpPost]
public async Task<ApiResponse<GetDrinksResponse>> GetDrinks(GetDrinksParameter parameter)
=> await ServiceCall(() => _service.GetDrinks(parameter));
[HttpPost]
public async Task<ApiResponse<GetDrinkDetailsResponse>> GetDrinkDetails(GetDrinkDetailsParameter parameter)
=> await ServiceCall(() => _service.GetDrinkDetails(parameter));
[HttpPost]
public async Task<ApiResponse<SaveDrinkResponse>> SaveDrink(SaveDrinkParameter parameter)
=> await ServiceCall(() => _service.SaveDrink(parameter));
private async Task<ApiResponse<T>> ServiceCall<T>(Func<Task<ApiResponse<T>>> 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<T>(new OperationResult(e));
}
}
}
}

View File

@@ -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<EnemiesController> logger)
{
_service = service;
_logger = logger;
}
[HttpPost]
public async Task<ApiResponse<GetEnemiesResponse>> GetEnemies(GetEnemiesParameter parameter)
=> await ServiceCall(() => _service.GetEnemies(parameter));
[HttpPost]
public async Task<ApiResponse<GetEnemyResponse>> GetEnemy(GetEnemyParameter parameter)
=> await ServiceCall(() => _service.GetEnemy(parameter));
[HttpPost]
public async Task<ApiResponse<SaveEnemyResponse>> SaveEnemy(SaveEnemyParameter parameter)
=> await ServiceCall(() => _service.SaveEnemy(parameter));
[HttpPost]
public async Task<ApiResponse<DeleteEnemyResponse>> DeleteEnemy(DeleteEnemyParameter parameter)
=> await ServiceCall(() => _service.DeleteEnemy(parameter));
private async Task<ApiResponse<T>> ServiceCall<T>(Func<Task<ApiResponse<T>>> 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<T>(new OperationResult(e));
}
}
}
}

View File

@@ -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<EpisodesController> logger, EpisodesService episodesService)
{
_logger = logger;
_episodesService = episodesService;
}
[HttpPost]
public async Task<ApiResponse<GetEpisodesResponse>> 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<GetEpisodesResponse>(new OperationResult(e));
}
}
[HttpPost]
public async Task<ApiResponse<GetEpisodeResponse>> 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<GetEpisodeResponse>(new OperationResult(e));
}
}
[HttpPost]
public async Task<ApiResponse<SaveEpisodeResponse>> 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<SaveEpisodeResponse>(new OperationResult(e));
}
}
}
}

View File

@@ -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<PlayersController> logger, PlayersService service)
{
_logger = logger;
_service = service;
}
private async Task<ApiResponse<T>> ServiceCall<T>(Func<Task<ApiResponse<T>>> 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<T>(new OperationResult(e));
}
}
[HttpPost]
public async Task<ApiResponse<GetPlayersResponse>> GetPlayers(GetPlayersParameter parameter)
=> await ServiceCall(() => _service.GetPlayers(parameter));
[HttpPost]
public async Task<ApiResponse<GetPlayerDetailsResponse>> GetPlayerDetails(GetPlayerDetailsParameter parameter)
=> await ServiceCall(() => _service.GetPlayerDetails(parameter));
[HttpPost]
public async Task<ApiResponse<SavePlayerResponse>> SavePlayer(SavePlayerParameter parameter)
=> await ServiceCall(() => _service.SavePlayer(parameter));
[HttpPost]
public async Task<ApiResponse<DeletePlayerResponse>> DeletePlayers(DeletePlayerParameter parameter)
=> await ServiceCall(() => _service.DeletePlayers(parameter));
}
}

View File

@@ -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<SeasonsController> logger, SeasonsService seasonsService)
{
_seasonsService = seasonsService;
_logger = logger;
}
[HttpPost]
public async Task<ApiResponse<GetSeasonsResponse>> 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<GetSeasonsResponse>(new OperationResult(e));
}
}
[HttpPost]
public async Task<ApiResponse<GetSeasonResponse>> 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<GetSeasonResponse>(new OperationResult(e));
}
}
[HttpPost]
public async Task<ApiResponse<SaveSeasonResponse>> 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<SaveSeasonResponse>(new OperationResult(e));
}
}
}
}

View File

@@ -26,4 +26,17 @@
<ItemGroup>
<ProjectReference Include="..\EstusShots.Shared\EstusShots.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Controllers\Controllers.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Controllers.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<Compile Update="Controllers\Controllers.cs">
<DependentUpon>Controllers.tt</DependentUpon>
</Compile>
</ItemGroup>
</Project>

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<ApiResponse<DeletePlayerResponse>> DeletePlayers(DeletePlayerParameter parameter)
public Task<ApiResponse<DeletePlayerResponse>> DeletePlayer(DeletePlayerParameter parameter)
{
throw new System.NotImplementedException();
}

View File

@@ -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;