I'm trying to abstract multiple client methods down to a single method or to a small amount of methods as possible. This is due to the fact that my client page is nearly 350 lines of code long. Any help would be appreciated.
My entire client page is below, as well as what I have come up with so far to abstract them all.
public async Task<IEnumerable<MessageTemplateDto>> GetAllMessageTemplatesAsync() => await Call<IEnumerable<MessageTemplateDto>>("messagetemplate");
private async Task Call(string url)
{
var response = await _httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<IEnumerable<MessageTemplateDto>>(responseStream);
}
using System.Text;
using System.Text.Json;
using Newtonsoft.Json;
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace Kmpt.Extensions.SmsComms;
public class SmsCommsClient
{
private readonly HttpClient _httpClient;
public SmsCommsClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
/// <summary>
/// This method calls the remote source (HTTP GET) to retrieve all message templates and deserializes the reponse stream into a collection of MessageTemplateDto's
/// </summary>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns> The MessageTemplateDto if successful</returns>
public async Task<IEnumerable<MessageTemplateDto>> GetAllMessageTemplatesAsync()
{
var response = await _httpClient.GetAsync("messagetemplates");
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<IEnumerable<MessageTemplateDto>>(responseStream);
}
/// <summary>
/// This method calls the remote source (HTTP GET) to retrieve a single message templates and deserializes the reponse stream into a single MessageTemplateDto
/// </summary>
/// <param name="id">The Id of the message template</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>The MessageTemplateDto if successful</returns>
public async Task<MessageTemplateDto> GetMessageTemplatesByIdAsync(int id)
{
var response = await _httpClient.GetAsync($"messagetemplates/{id}");
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<MessageTemplateDto>(responseStream);
}
/// <summary>
/// This method calls the remote source (HTTP Post) to create a new message template and deserializes the reponse stream into a single MessageTemplateDto
/// </summary>
/// <param name="newMessTempDto">newMessTempDto is the parameter name for the new message template that will be created, it is a dto type</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>The MessageTemplateDto if successful</returns>
public async Task<MessageTemplateDto> AddNewMessageTemplateAsync(MessageTemplateDto newMessTempDto)
{
var json = JsonConvert.SerializeObject(newMessTempDto);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync("messagetemplates", data);
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<MessageTemplateDto>(responseStream);
}
/// <summary>
/// This method calls the remote source (HTTP Put) to modify a message template and deserializes the reponse stream into a single MessageTemplateDto
/// </summary>
/// <param name="modMessTemDto">modMessTemDto is the parameter name for the new message template that will be modified, it is a dto type</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>The MessageTemplateDto if successful</returns>
public async Task<MessageTemplateDto> ModifyMessageTemplateAsync(MessageTemplateDto modMessTemDto)
{
var json = JsonConvert.SerializeObject(modMessTemDto);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PutAsync("messagetemplates", data);
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<MessageTemplateDto>(responseStream);
}
/// <summary>
/// This method calls the remote source (HTTP Delete) to delete a message template
/// </summary>
/// <param name="id">The Id of the message template that needs to be deleted</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>Does not return anything</returns>
public async Task DeleteMessageTemplateAsync(int id)
{
var response = await _httpClient.DeleteAsync($"messagetemplates/{id}");
response.EnsureSuccessStatusCode();
}
/// <summary>
/// This method calls the remote source (HTTP Get) to retrieve all address books and deserializes the reponse stream into a collection of AddressBookDto's
/// </summary>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>A collection of AddressBookEntryDto's if successful</returns>
public async Task<IEnumerable<AddressBookEntryDto>> GetAllAddressBooksAsync()
{
var response = await _httpClient.GetAsync("addressbooks");
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<IEnumerable<AddressBookEntryDto>>(responseStream);
}
/// <summary>
/// This method calls the remote source (HTTP Get) to retrieve a single address book and deserializes the reponse stream into a single AddressBookDto
/// </summary>
/// <param name="id">The Id of the message template</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>The AddressBookEntryDto if successful</returns>
public async Task<AddressBookEntryDto> GetAddressBookByIdAsync(int id)
{
var response = await _httpClient.GetAsync($"addressbooks/{id}");
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<AddressBookEntryDto>(responseStream);
}
/// <summary>
/// This method calls the remote source (HTTP Post) to create a single address book
/// </summary>
/// <param name="newAddBookDto">The parameter name for the address book that needs to be added</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>Does not return anything</returns>
public async Task AddNewAddressBookAsync(AddressBookEntryDto newAddBookDto)
{
var json = JsonConvert.SerializeObject(newAddBookDto);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync("addressbooks", data);
response.EnsureSuccessStatusCode();
}
/// <summary>
/// This method calls the remote source (HTTP Put) to modify a single address book
/// </summary>
/// <param name="modAddBookDto">The parameter name for the address book that needs to be changed</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>The AddressBookEntryDto if successful</returns>
public async Task<AddressBookEntryDto> ModifyAddressBookAsync(AddressBookEntryDto modAddBookDto)
{
var json = JsonConvert.SerializeObject(modAddBookDto);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PutAsync("addressbooks", data);
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<AddressBookEntryDto>(responseStream);
}
/// <summary>
/// This method calls the remote source (HTTP DELETE) to delete a single address book
/// </summary>
/// <param name="id">The id for the address book that needs to be deleted</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>Does not return anything</returns>
public async Task DeleteAddressBookAsync(int id)
{
var response = await _httpClient.DeleteAsync($"addressbooks/{id}");
response.EnsureSuccessStatusCode();
}
/// <summary>
/// This method calls the remote source (HTTP GET) to retrieve all groups
/// </summary>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>The GroupDto if successful</returns>
public async Task<IEnumerable<GroupDto>> GetAllGroupsAsync()
{
var response = await _httpClient.GetAsync("groups");
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<IEnumerable<GroupDto>>(responseStream);
}
/// <summary>
/// This method calls the remote source (HTTP GET) to retrieve a single group
/// </summary>
/// <param name="id">The id for the correct group</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>The GroupDto if successful</returns>
public async Task<GroupDto> GetGroupByIdAsync(int id)
{
var response = await _httpClient.GetAsync($"groups/{id}");
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<GroupDto>(responseStream);
}
/// <summary>
/// This method calls the remote source (HTTP POST) to add a new group
/// </summary>
/// <param name="newMessageTemplate">The object that contains the information to create a new group</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>The GroupDto if successful</returns>
public async Task<MembershipDto> AddNewGroupAsync(GroupDto newMessageTemplate)
{
var json = JsonConvert.SerializeObject(newMessageTemplate);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync("groups", data);
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<MembershipDto>(responseStream);
}
/// <summary>
/// This method calls the remote source (HTTP PUT) to modify a group
/// </summary>
/// <param name="modGroupDto">The object that contains the information to modify a group</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>Does not return anything</returns>
public async Task ModifyGroupAsync(GroupDto modGroupDto)
{
var json = JsonConvert.SerializeObject(modGroupDto);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PutAsync("groups", data);
response.EnsureSuccessStatusCode();
}
/// <summary>
/// This method calls the remote source (HTTP DELETE) to delete a group
/// </summary>
/// <param name="id">The id of the group that needs to be deleted</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>Does not return anything</returns>
public async Task DeleteGroup(int id)
{
var response = await _httpClient.DeleteAsync($"groups/{id}");
response.EnsureSuccessStatusCode();
}
/// <summary>
/// This method calls the remote source (HTTP POST) to send the message information to the controller
/// </summary>
/// <param name="numbers">The list of numbers that the message will be sent to</param>
/// <param name="body">The body of the message that will be sent</param>
/// <param name="sentBy">The person that the message was sent by</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>Does not return anything</returns>
public async Task SendMessageAsync(MessageContentDto messageContent)
{
var json = JsonConvert.SerializeObject(messageContent);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync("messaging", data);
response.EnsureSuccessStatusCode();
}
/// <summary>
/// This method calls the remote source (HTTP GET) to retrieve all memberships
/// </summary>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>The MembershipDto if successful</returns>
public async Task<IEnumerable<MembershipDto>> GetAllMembershipsAsync()
{
var response = await _httpClient.GetAsync("membership");
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<IEnumerable<MembershipDto>>(responseStream);
}
/// <summary>
/// This method calls the remote source (HTTP GET) to retrieve a single membership
/// </summary>
/// <param name="id">The id of the membership to retrieve</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>The MembershipDto if successful</returns>
public async Task<MembershipDto> GetMembershipByIdAsync(int id)
{
var response = await _httpClient.GetAsync($"membership/{id}");
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<MembershipDto>(responseStream);
}
/// <summary>
/// This method calls the remote source (HTTP POST) to create a new membership
/// </summary>
/// <param name="newMembershipDto">The object that contains the information to create a new membership</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>The MembershipDto if successful</returns>
public async Task<MembershipDto> AddNewMembershipAsync(MembershipDto newMembershipDto)
{
var json = JsonConvert.SerializeObject(newMembershipDto);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync("membership", data);
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync
<MembershipDto>(responseStream);
}
/// <summary>
/// This method calls the remote source (HTTP Delete) to delete a membership
/// </summary>
/// <param name="addressBookId">The addressBookId of the membership</param>
/// <param name="groupId">The groupId of the membership</param>
/// <exception cref="HttpRequestException">The EnsureSuccessStatusCode needs to be handled</exception>
/// <returns>Does not return anything</returns>
public async Task DeleteMembership(int addressBookId, int groupId)
{
var response = await _httpClient.DeleteAsync($"membership/{addressBookId}/{groupId}");
response.EnsureSuccessStatusCode();
}
}
Edit: As there wasn't a clear question before I'm going to put it here. What is the simplest/easiest/best way to abstract them?
CodePudding user response:
the usual way to go about this is to check the shared pieces of code and extract them. The differences should be passed as parameters. For the generic part you would introduce a new generic parameter <T>
and replace all generic parts with it. For example the get methods
public async Task<MessageTemplateDto> GetMessageTemplatesByIdAsync(int id)
{
var response = await _httpClient.GetAsync($"messagetemplates/{id}");
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync<MessageTemplateDto>(responseStream);
}
would look like this:
public async Task<T> GetByIdString<T>(string parameter) where T : class
Then you take the entire inner code of GetMessageTemplatesByIdAsync
, replace the MessageTemplateDto
by T
public async Task<T> GetByIdString<T>(string parameter) where T : class
{
var response = await _httpClient.GetAsync(parameter);
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync<T>(responseStream);
}
and you would call it like:
public async Task<MessageTemplateDto> GetMessageTemplatesByIdAsync(int id)
{
return await get<MessageTemplateDto>("$"messagetemplates/{id}");
}
The same way you would extract the set methods. take the differences as parameters into the extracted methods which should contain the shared code.
The delete methods should be the easiest, since they only need the passed string as parameter
CodePudding user response:
Looks like you want to use the repository pattern. The following creates an interface, base class and a single repository for one of your data types. You would inject these into your constructor to get access to each:
public interface IRepository<T>
{
Task<IEnumerable<T>> GetAllAsync();
Task<T> GetAsync(int id);
Task<T> AddAsync(T item);
Task<T> UpdateAsync(T item);
Task DeleteAsync(int id);
}
public abstract class RepositoryBase<T> : IRepository<T>
{
private readonly HttpClient _httpClient;
private readonly string _url;
protected RepositoryBase(string url, HttpClient httpClient)
{
_url = url;
_httpClient = httpClient;
}
public async Task<IEnumerable<T>> GetAllAsync()
{
var response = await _httpClient.GetAsync(_url);
response.EnsureSuccessStatusCode();
string body = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<IEnumerable<T>>(body);
}
public async Task<T> GetAsync(int id)
{
var response = await _httpClient.GetAsync($"{_url}/{id}");
response.EnsureSuccessStatusCode();
string body = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(body);
}
public async Task<T> AddAsync(T item)
{
var json = JsonConvert.SerializeObject(item);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(_url, data);
response.EnsureSuccessStatusCode();
string body = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(body);
}
public async Task<T> UpdateAsync(T item)
{
var json = JsonConvert.SerializeObject(item);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PutAsync(_url, data);
response.EnsureSuccessStatusCode();
string body = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(body);
}
public async Task DeleteAsync(int id)
{
var response = await _httpClient.DeleteAsync($"{_url}/{id}");
response.EnsureSuccessStatusCode();
}
}
public class MessageTemplateRepository : RepositoryBase<MessageTemplateDto>
{
public MessageTemplateRepository(HttpClient httpClient)
: base("messagetemplates", httpClient)
{
}
}