Basit Bir Rest Api Client Geliştirelim 2
2023-05-12
Bu versiyonda, bir dizi başlık bilgisi, özelleştirilmiş zaman aşımı süresi ve daha fazla hata kontrolü ekleyelim:
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
public class MyHttpClient : IDisposable
{
private readonly HttpClient _client;
public MyHttpClient(TimeSpan? timeout = null)
{
_client = new HttpClient();
if (timeout.HasValue)
{
_client.Timeout = timeout.Value;
}
}
private HttpRequestMessage CreateRequest(string uri, HttpMethod method, string jsonData = null, Dictionary<string, string> headers = null)
{
var request = new HttpRequestMessage(method, uri);
if (headers != null)
{
foreach (var header in headers)
{
request.Headers.Add(header.Key, header.Value);
}
}
if (!string.IsNullOrWhiteSpace(jsonData))
{
request.Content = new StringContent(jsonData, Encoding.UTF8, "application/json");
}
return request;
}
public async Task<HttpResponseMessage> SendRequestAsync(string uri, HttpMethod method, string jsonData = null, Dictionary<string, string> headers = null)
{
var request = CreateRequest(uri, method, jsonData, headers);
try
{
var response = await _client.SendAsync(request);
response.EnsureSuccessStatusCode();
return response;
}
catch (HttpRequestException ex)
{
throw new Exception($"{method} request to {uri} failed.", ex);
}
}
public async Task<string> GetAsync(string uri, Dictionary<string, string> headers = null) =>
(await SendRequestAsync(uri, HttpMethod.Get, null, headers)).Content.ReadAsStringAsync().Result;
public async Task<string> PostAsync(string uri, string jsonData, Dictionary<string, string> headers = null) =>
(await SendRequestAsync(uri, HttpMethod.Post, jsonData, headers)).Content.ReadAsStringAsync().Result;
public async Task<string> PutAsync(string uri, string jsonData, Dictionary<string, string> headers = null) =>
(await SendRequestAsync(uri, HttpMethod.Put, jsonData, headers)).Content.ReadAsStringAsync().Result;
public async Task<string> DeleteAsync(string uri, Dictionary<string, string> headers = null) =>
(await SendRequestAsync(uri, HttpMethod.Delete, null, headers)).Content.ReadAsStringAsync().Result;
public void Dispose()
{
_client?.Dispose();
}
}
Bu sınıf, IDisposable interface’ini uygular, bu da HttpClient nesnesini düzgün bir şekilde yok etmenizi sağlar. Yapıcı
(constructor), isteğe bağlı bir zaman aşımı süresi alır ve HttpClient‘ın Timeout özelliğini ayarlar.
SendRequestAsync metodu, istek oluşturma işlemini ayrı bir CreateRequest metoduna ayırır. Bu, kodun okunabilirliğini artırır ve istek oluşturma sürecinde daha fazla özelleştirmeye izin verir.
Ayrıca, SendRequestAsync metodu artık bir HttpResponseMessage döndürür, böylece istemci isteğin yanıt durum kodunu ve diğer özelliklerini kontrol edebilir.
HTTP istemcilerini daha verimli bir şekilde yönetmek için HttpClientFactory kullanalım, çünkü HttpClientFactory altta yatan
HttpClientHandler nesnelerini yönetir ve sunucu DNS değişikliklerini daha iyi ele alır.
Ek olarak, bu sınıf artık özelleştirilebilir bir HttpMessageHandler kabul ediyor, bu da istemcinin daha fazla özelleştirilebilirliğine olanak sağlıyor.
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
public class MyHttpClient : IDisposable
{
private readonly HttpClient _client;
public MyHttpClient(HttpClient client)
{
_client = client;
}
private HttpRequestMessage CreateRequest(string uri, HttpMethod method, string jsonData = null, Dictionary<string, string> headers = null)
{
var request = new HttpRequestMessage(method, uri);
if (headers != null)
{
foreach (var header in headers)
{
request.Headers.Add(header.Key, header.Value);
}
}
if (!string.IsNullOrWhiteSpace(jsonData))
{
request.Content = new StringContent(jsonData, Encoding.UTF8, "application/json");
}
return request;
}
public async Task<HttpResponseMessage> SendRequestAsync(string uri, HttpMethod method, string jsonData = null, Dictionary<string, string> headers = null)
{
var request = CreateRequest(uri, method, jsonData, headers);
try
{
var response = await _client.SendAsync(request);
response.EnsureSuccessStatusCode();
return response;
}
catch (HttpRequestException ex)
{
throw new Exception($"{method} request to {uri} failed.", ex);
}
}
public async Task<string> GetAsync(string uri, Dictionary<string, string> headers = null) =>
(await SendRequestAsync(uri, HttpMethod.Get, null, headers)).Content.ReadAsStringAsync().Result;
public async Task<string> PostAsync(string uri, string jsonData, Dictionary<string, string> headers = null) =>
(await SendRequestAsync(uri, HttpMethod.Post, jsonData, headers)).Content.ReadAsStringAsync().Result;
public async Task<string> PutAsync(string uri, string jsonData, Dictionary<string, string> headers = null) =>
(await SendRequestAsync(uri, HttpMethod.Put, jsonData, headers)).Content.ReadAsStringAsync().Result;
public async Task<string> DeleteAsync(string uri, Dictionary<string, string> headers = null) =>
(await SendRequestAsync(uri, HttpMethod.Delete, null, headers)).Content.ReadAsStringAsync().Result;
public void Dispose()
{
_client?.Dispose();
}
}
Bu sınıfı bir HttpClientFactory ile kullanmak için aşağıdaki gibi bir şey yapabilirsiniz:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<MyHttpClient>();
}
Ve sonra istemciyi aşağıdaki gibi enjekte edebilirsiniz:
public class MyController : ControllerBase
{
private readonly MyHttpClient _client;
public MyController(MyHttpClient client)
{
_client = client;
}
}
