Implement unified API controller pattern

This commit is contained in:
2020-02-29 14:13:46 +01:00
parent e49b6791a0
commit eee5661f9a
16 changed files with 414 additions and 138 deletions

View File

@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using EstusShots.Shared.Dto;
using EstusShots.Client.Routes;
using EstusShots.Shared.Interfaces;
using EstusShots.Shared.Models;
namespace EstusShots.Client
@@ -13,49 +13,52 @@ namespace EstusShots.Client
{
private readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
PropertyNameCaseInsensitive = true
};
private string ApiUrl { get; }
private HttpClient HttpClient { get; }
public string ApiUrl { get; }
// API Routes
public Seasons Seasons { get; }
/// <summary>
/// Creates a new instance of <see cref="EstusShotsClient"/>
/// </summary>
/// <param name="apiUrl">Base URL of the Estus Shots API host</param>
public EstusShotsClient(string apiUrl)
{
ApiUrl = apiUrl;
HttpClient = new HttpClient {Timeout = TimeSpan.FromSeconds(10)};
Seasons = new Seasons(this);
}
public async Task<(OperationResult, List<Season>)> GetSeasons()
/// <summary>
/// Generic method to post a request to the API
/// </summary>
/// <param name="url">URL to the desired action</param>
/// <param name="parameter">The API parameter object instance</param>
/// <typeparam name="TResult">API response class that implements <see cref="IApiResponse"/></typeparam>
/// <typeparam name="TParam">API parameter class that implements <see cref="IApiParameter"/></typeparam>
/// <returns></returns>
public async Task<ApiResponse<TResult>> PostToApi<TResult, TParam>(string url, TParam parameter)
where TParam : IApiParameter, new()
where TResult : class, IApiResponse, new()
{
try
{
var response = await HttpClient.GetAsync(ApiUrl + "seasons");
var jsonData = await response.Content.ReadAsStringAsync();
var data = JsonSerializer.Deserialize<List<Season>>(jsonData, _serializerOptions);
return (new OperationResult(), data);
var serialized = JsonSerializer.Serialize(parameter);
var content = new StringContent(serialized, Encoding.UTF8, "application/json");
var response = await HttpClient.PostAsync(url, content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ApiResponse<TResult>>(json, _serializerOptions);
return result;
}
catch (Exception e)
{
return (new OperationResult(e), new List<Season>());
}
}
public async Task<(OperationResult, Guid)> CreateSeason(Season season)
{
try
{
var content = new StringContent(JsonSerializer.Serialize(season), Encoding.UTF8, "application/json");
var response = await HttpClient.PostAsync(ApiUrl + "season", content);
if (!response.IsSuccessStatusCode)
{
return (new OperationResult(false, response.ReasonPhrase), Guid.Empty);
}
// TODO should give the created id
return (new OperationResult(), Guid.Empty);
}
catch (Exception e)
{
return (new OperationResult(e), Guid.Empty);
return new ApiResponse<TResult>(new OperationResult(e));
}
}

View File

@@ -0,0 +1,30 @@
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<ApiResponse<GetSeasonsResponse>> GetSeasons(GetSeasonsParameter parameter) =>
await _client.PostToApi<GetSeasonsResponse, GetSeasonsParameter>(ActionUrl(), parameter);
public async Task<ApiResponse<GetSeasonResponse>> GetSeason(GetSeasonParameter parameter) =>
await _client.PostToApi<GetSeasonResponse, GetSeasonParameter>(ActionUrl(), parameter);
public async Task<ApiResponse<SaveSeasonResponse>> SaveSeason(SaveSeasonParameter parameter)=>
await _client.PostToApi<SaveSeasonResponse, SaveSeasonParameter>(ActionUrl(), parameter);
}
}