namespace BookServiceClientApp
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("Client app, wait for service");
Console.ReadLine();
RegisterServices();
var test = Container.GetRequiredService<SampleRequestClient>();
await test.ReadChaptersAsync();
await test.ReadChapterAsync();
await test.ReadNotExistingChapterAsync();
await test.ReadXmlAsync();
await test.AddChapterAsync();
await test.UpdateChapterAsync();
await test.RemoveChapterAsync();
Console.ReadLine();
}
public static void RegisterServices()
{
var services = new ServiceCollection();
services.AddSingleton<UrlService>();
services.AddSingleton<BookChapterClientService>();
services.AddTransient<SampleRequestClient>();
Container = services.BuildServiceProvider();
}
public static IServiceProvider Container { get; private set; }
}
}
namespace BookServiceClientApp
{
public class SampleRequestClient
{
private readonly UrlService _urlService;
private readonly BookChapterClientService _client;
public SampleRequestClient(UrlService urlService, BookChapterClientService client)
{
_urlService = urlService;
_client = client;
}
public async Task ReadChaptersAsync()
{
Console.WriteLine(nameof(ReadChaptersAsync));
IEnumerable<BookChapter> chapters = await _client.GetAllAsync(_urlService.BooksApi);
foreach (BookChapter chapter in chapters)
{
Console.WriteLine(chapter.Title);
}
Console.WriteLine();
}
public async Task ReadChapterAsync()
{
Console.WriteLine(nameof(ReadChapterAsync));
var chapters = await _client.GetAllAsync(_urlService.BooksApi);
Guid id = chapters.First().Id;
BookChapter chapter = await _client.GetAsync(_urlService.BooksApi + id);
Console.WriteLine($"{chapter.Number} {chapter.Title}");
Console.WriteLine();
}
public async Task ReadNotExistingChapterAsync()
{
Console.WriteLine(nameof(ReadNotExistingChapterAsync));
string requestedIdentifier = Guid.NewGuid().ToString();
try
{
BookChapter chapter = await _client.GetAsync(
_urlService.BooksApi + requestedIdentifier.ToString());
Console.WriteLine($"{chapter.Number} {chapter.Title}");
}
catch (HttpRequestException ex) when (ex.Message.Contains("404"))
{
Console.WriteLine($"book chapter with the identifier " +
$"{requestedIdentifier} not found");
}
Console.WriteLine();
}
public async Task ReadXmlAsync()
{
Console.WriteLine(nameof(ReadXmlAsync));
XElement chapters = await _client.GetAllXmlAsync(_urlService.BooksApi);
Console.WriteLine(chapters);
Console.WriteLine();
}
public async Task AddChapterAsync()
{
Console.WriteLine(nameof(AddChapterAsync));
BookChapter chapter = new BookChapter
{
Number = 42,
Title = "ASP.NET Web API",
Pages = 35
};
chapter = await _client.PostAsync(_urlService.BooksApi, chapter);
Console.WriteLine($"added chapter {chapter.Title} with id {chapter.Id}");
Console.WriteLine();
}
public async Task UpdateChapterAsync()
{
Console.WriteLine(nameof(UpdateChapterAsync));
var chapters = await _client.GetAllAsync(_urlService.BooksApi);
var chapter = chapters.SingleOrDefault(c => c.Title == "Windows Store Apps");
if (chapter != null)
{
chapter.Number = 32;
chapter.Title = "Windows Apps";
await _client.PutAsync(_urlService.BooksApi + chapter.Id, chapter);
Console.WriteLine($"updated chapter {chapter.Title}");
}
Console.WriteLine();
}
public async Task RemoveChapterAsync()
{
Console.WriteLine(nameof(RemoveChapterAsync));
var chapters = await _client.GetAllAsync(_urlService.BooksApi);
var chapter = chapters.SingleOrDefault(c => c.Title == "ASP.NET Web Forms");
if (chapter != null)
{
await _client.DeleteAsync(_urlService.BooksApi + chapter.Id);
Console.WriteLine($"removed chapter {chapter.Title}");
}
Console.WriteLine();
}
}
}
namespace BookServiceClientApp.Services
{
public class UrlService
{
public string BaseAddress => "http://localhost:1079/";
public string BooksApi => "api/BookChapters/";
}
}
namespace BookServiceClientApp.Services
{
public abstract class HttpClientService<T> : IDisposable
where T : class
{
private HttpClient _httpClient;
private readonly UrlService _urlService;
public HttpClientService(UrlService urlService)
{
_urlService = urlService;
_httpClient = new HttpClient();
_httpClient.BaseAddress = new Uri(_urlService.BaseAddress);
}
private async Task<string> GetInternalAsync(string requestUri)
{
if (_objectDisposed) throw new ObjectDisposedException(nameof(_httpClient));
HttpResponseMessage resp = await _httpClient.GetAsync(requestUri);
Console.WriteLine($"status from GET {resp.StatusCode}");
resp.EnsureSuccessStatusCode();
return await resp.Content.ReadAsStringAsync();
}
public async virtual Task<T> GetAsync(string requestUri)
{
string json = await GetInternalAsync(requestUri);
return JsonConvert.DeserializeObject<T>(json);
}
public async virtual Task<IEnumerable<T>> GetAllAsync(string requestUri)
{
string json = await GetInternalAsync(requestUri);
return JsonConvert.DeserializeObject<IEnumerable<T>>(json);
}
public async Task<XElement> GetAllXmlAsync(string requestUri)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_urlService.BaseAddress);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/xml"));
HttpResponseMessage resp = await client.GetAsync(requestUri);
Console.WriteLine($"status from GET {resp.StatusCode}");
resp.EnsureSuccessStatusCode();
string xml = await resp.Content.ReadAsStringAsync();
XElement chapters = XElement.Parse(xml);
return chapters;
}
}
public async Task<T> PostAsync(string uri, T item)
{
if (_objectDisposed) throw new ObjectDisposedException(nameof(_httpClient));
string json = JsonConvert.SerializeObject(item);
HttpContent content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage resp = await _httpClient.PostAsync(uri, content);
Console.WriteLine($"status from POST {resp.StatusCode}");
resp.EnsureSuccessStatusCode();
Console.WriteLine($"added resource at {resp.Headers.Location}");
json = await resp.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(json);
}
public async Task PutAsync(string uri, T item)
{
if (_objectDisposed) throw new ObjectDisposedException(nameof(_httpClient));
string json = JsonConvert.SerializeObject(item);
HttpContent content = new StringContent(json, Encoding.UTF8,
"application/json");
HttpResponseMessage resp = await _httpClient.PutAsync(uri, content);
Console.WriteLine($"status from PUT {resp.StatusCode}");
resp.EnsureSuccessStatusCode();
}
public async Task DeleteAsync(string uri)
{
if (_objectDisposed) throw new ObjectDisposedException(nameof(_httpClient));
HttpResponseMessage resp = await _httpClient.DeleteAsync(uri);
Console.WriteLine($"status from DELETE {resp.StatusCode}");
resp.EnsureSuccessStatusCode();
}
#region IDisposable Support
private bool _objectDisposed = false;
protected virtual void Dispose(bool disposing)
{
if (!_objectDisposed)
{
if (disposing)
{
_httpClient?.Dispose();
}
_objectDisposed = true;
}
}
public void Dispose()
{
Dispose(true);
}
#endregion
}
}
namespace BookServiceClientApp.Services
{
public class BookChapterClientService : HttpClientService<BookChapter>
{
public BookChapterClientService(UrlService urlService)
: base(urlService) { }
public override async Task<IEnumerable<BookChapter>> GetAllAsync(string requestUri)
{
IEnumerable<BookChapter> chapters = await base.GetAllAsync(requestUri);
return chapters.OrderBy(c => c.Number);
}
}
}
namespace BookServiceClientApp.Models
{
public class BookChapter
{
public Guid Id { get; set; }
public int Number { get; set; }
public string Title { get; set; }
public int Pages { get; set; }
}
}