.NET ile HTTP
Bu makalede bağımlılık ekleme (DI), günlüğe kaydetme ve yapılandırma gibi çeşitli .NET temel bilgileriyle ve türlerini IHttpClientFactory HttpClient kullanmayı öğrenirsiniz. Tür, HttpClient 2012'de .NET Framework 4.5'te tanıtıldı. Başka bir deyişle, bir süredir böyle. HttpClient , HTTP istekleri yapmak ve bir tarafından tanımlanan web kaynaklarından HTTP yanıtlarını işlemek için Uri kullanılır. HTTP protokolü, tüm internet trafiğinin büyük çoğunluğunu sağlar.
Modern uygulama geliştirme ilkeleri en iyi yöntemlerin yol gösterirken, özel yapılandırmalarla örnekler oluşturan IHttpClientFactory HttpClient bir fabrika soyutlama olarak görev almaktadır. IHttpClientFactory .NET Core 2.1'de tanıtıldı. Yaygın HTTP tabanlı .NET iş yükleri, kolay bir şekilde üçüncü taraf ara yazılımlara karşı, karşılarına çıkar ve geçici hata işlemeden faydalanabilirsiniz.
Türü IHttpClientFactory keşfetme
Bu makaledeki tüm örnek kaynak kodu, Microsoft.Extensions.Http NuGet. Buna ek olarak, "nerdy" için HTTP GET isteklerinde bulunduracak İnternetLide Norris Veritabanı ücretsiz API'si kullanılır.
Uzantı yöntemlerden herhangi AddHttpClient birini çağırarak ve ile ilgili hizmetlerini IHttpClientFactory 'ye eklersiniz. IServiceCollection Türü IHttpClientFactory aşağıdaki avantajları sunar:
- Sınıfı
HttpClientDI'ye hazır bir tür olarak kullanıma sağlar. - Mantıksal örnekleri adlandırmak ve yapılandırmak için merkezi bir
HttpClientkonum sağlar. - içinde işleyiciler için delete aracılığıyla giden ara yazılım kavramını
HttpClientkodlar. - içinde işleyicileri seçme avantajını elde etmek için Polly tabanlı ara yazılım için uzantı yöntemleri
HttpClientsağlar. - Temel alınan örneklerin havuzlarını ve yaşam HttpClientHandler sürelerini yönetir. Otomatik yönetim, yaşam sürelerini el ile yönetme sırasında oluşan yaygın Etki Alanı Adı Sistemi (DNS)
HttpClientsorunlarını önler. - Fabrika tarafından oluşturulan istemciler aracılığıyla gönderilen tüm ILogger istekler için yapılandırılabilir bir günlük deneyimi (aracılığıyla) ekler.
Tüketim desenleri
Bir uygulamada çeşitli IHttpClientFactory yollarla kullanılabilir:
En iyi yaklaşım, uygulamanın gereksinimlerine bağlıdır.
Temel kullanım
'i kaydetmek IHttpClientFactory için çağrısına AddHttpClient tıklayın:
using BasicHttp.Example;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHttpClient();
services.AddTransient<JokeService>();
})
.Build();
Hizmetleri kullanmak IHttpClientFactory için, DI ile oluşturucu parametresi olarak parametresini gerekli hale alabilir. Aşağıdaki kod bir IHttpClientFactory örnek oluşturmak için HttpClient kullanır:
using System.Net.Http.Json;
using Microsoft.Extensions.Logging;
using Shared;
namespace BasicHttp.Example;
public class JokeService
{
private readonly IHttpClientFactory _httpClientFactory = null!;
private readonly ILogger<JokeService> _logger = null!;
public JokeService(
IHttpClientFactory httpClientFactory,
ILogger<JokeService> logger) =>
(_httpClientFactory, _logger) = (httpClientFactory, logger);
public async Task<string> GetRandomJokeAsync()
{
// Create the client
HttpClient client = _httpClientFactory.CreateClient();
try
{
// Make HTTP GET request
// Parse JSON response deserialize into ChuckNorrisJoke type
ChuckNorrisJoke? result = await client.GetFromJsonAsync<ChuckNorrisJoke>(
"https://api.icndb.com/jokes/random?limitTo=[nerdy]",
DefaultJsonSerialization.Options);
if (result?.Value?.Joke is not null)
{
return result.Value.Joke;
}
}
catch (Exception ex)
{
_logger.LogError("Error getting something fun to say: {Error}", ex);
}
return "Oops, something has gone wrong - that's not funny at all!";
}
}
Yukarıdaki IHttpClientFactory örnekte olduğu gibi kullanmak, mevcut bir uygulamayı yeniden düzenlemenin iyi bir yolu olabilir. Bunun nasıl kullanıldıkları üzerinde HttpClient hiçbir etkisi yoktur. Örneklerin HttpClient var olan bir uygulamada oluşturulacak olduğu yerlerde, bu oluşumları çağrısıyla CreateClient değiştirin.
Adlandırılmış istemciler
Adlandırılmış istemciler şu zaman iyi bir seçimdir:
- Uygulamanın birçok farklı kullanımı
HttpClientgerekir. - Birçok
HttpClientörneğin yapılandırması farklıdır.
adlı bir için HttpClient yapılandırma, içinde kayıt sırasında belirtilebilir: ConfigureServices
using NamedHttp.Example;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
string httpClientName = context.Configuration["JokeHttpClientName"];
services.AddHttpClient(
httpClientName,
client =>
{
// Set the base address of the named client.
client.BaseAddress = new Uri("https://api.icndb.com/");
// Add a user-agent default request header.
client.DefaultRequestHeaders.UserAgent.ParseAdd("dotnet-docs");
});
services.AddTransient<JokeService>();
})
.Build();
Önceki kodda, istemci ile yapılandırılır:
- altındaki yapılandırmadan çekilir bir
"JokeHttpClientName"ad. - Temel
https://api.icndb.com/adres. - Üst
"User-Agent"bilgi.
Http istemci adlarını belirtmek için yapılandırmayı kullanabilirsiniz; bu, ekleme ve oluşturmada istemcilerin yanlış adlarından kaçınmanıza yardımcı olur. Bu örnekte, HTTP istemci adını yapılandırmak için appsettings.json dosyası kullanılır:
{
"JokeHttpClientName": "ChuckNorrisJokeApi"
}
Bu yapılandırmayı genişletmek ve HTTP istemcinizin nasıl çalışmasına ilişkin daha fazla ayrıntı depolamak kolaydır. Daha fazla bilgi için bkz. .NET'te yapılandırma.
İstemci oluşturma
Her zaman CreateClient çağrılır:
- yeni bir
HttpClientörneği oluşturulur. - Yapılandırma eylemi çağrılır.
Adlandırılmış bir istemci oluşturmak için adını içine CreateClient girin:
using System.Net.Http.Json;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Shared;
namespace NamedHttp.Example;
public class JokeService
{
private readonly IHttpClientFactory _httpClientFactory = null!;
private readonly IConfiguration _configuration = null!;
private readonly ILogger<JokeService> _logger = null!;
public JokeService(
IHttpClientFactory httpClientFactory,
IConfiguration configuration,
ILogger<JokeService> logger) =>
(_httpClientFactory, _configuration, _logger) =
(httpClientFactory, configuration, logger);
public async Task<string> GetRandomJokeAsync()
{
// Create the client
string httpClientName = _configuration["JokeHttpClientName"];
HttpClient client = _httpClientFactory.CreateClient(httpClientName);
try
{
// Make HTTP GET request
// Parse JSON response deserialize into ChuckNorrisJoke type
ChuckNorrisJoke? result = await client.GetFromJsonAsync<ChuckNorrisJoke>(
"jokes/random?limitTo=[nerdy]",
DefaultJsonSerialization.Options);
if (result?.Value?.Joke is not null)
{
return result.Value.Joke;
}
}
catch (Exception ex)
{
_logger.LogError("Error getting something fun to say: {Error}", ex);
}
return "Oops, something has gone wrong - that's not funny at all!";
}
}
Yukarıdaki kodda HTTP isteğinin bir konak adı belirtmesi gerekm yok. İstemci için yapılandırılan temel adres kullanılırken kod yalnızca yolu geçebilirsiniz.
Türe bağlı istemciler
Türe bağlı istemciler:
- Dizeleri anahtar olarak kullanmaya gerek kalmadan adlandırılmış istemcilerle aynı özellikleri sağlar.
- İstemcileri tüketen IntelliSense ve derleyici yardımı sağlama.
- Yapılandırmak ve belirli bir ile etkileşim kurmak için tek bir konum
HttpClientsağlama. Örneğin, türü tek bir istemci kullanılabilir:- Tek bir arka uç uç noktası için.
- Uç noktayla ilgili tüm mantığı kapsülleme.
- DI ile çalışma ve uygulamaya gerektiğinde ekleme.
Türü türüne sahip bir istemci, HttpClient oluşturucusnda bir parametre kabul eder:
using System.Net.Http.Json;
using Microsoft.Extensions.Logging;
using Shared;
namespace TypedHttp.Example;
public sealed class JokeService
{
private readonly HttpClient _httpClient = null!;
private readonly ILogger<JokeService> _logger = null!;
public JokeService(
HttpClient httpClient,
ILogger<JokeService> logger) =>
(_httpClient, _logger) = (httpClient, logger);
public async Task<string> GetRandomJokeAsync()
{
try
{
// Make HTTP GET request
// Parse JSON response deserialize into ChuckNorrisJoke type
ChuckNorrisJoke? result = await _httpClient.GetFromJsonAsync<ChuckNorrisJoke>(
"https://api.icndb.com/jokes/random?limitTo=[nerdy]",
DefaultJsonSerialization.Options);
if (result?.Value?.Joke is not null)
{
return result.Value.Joke;
}
}
catch (Exception ex)
{
_logger.LogError("Error getting something fun to say: {Error}", ex);
}
return "Oops, something has gone wrong - that's not funny at all!";
}
}
Yukarıdaki kodda:
- Türe sahip istemci hizmet koleksiyonuna ekleniyor olduğunda yapılandırma ayarlanır.
HttpClient, sınıf kapsamlı değişken (alan) olarak atanır ve açık API'lerle kullanılır.
İşlevselliği ortaya çıkaran API'ye özgü HttpClient yöntemler oluşturulabilir. Örneğin, GetRandomJokeAsync yöntemi rastgele bir rastgele almak için kodu kapsüller.
Aşağıdaki kod, türü AddHttpClient türü doğru olan bir istemci ConfigureServices sınıfını kaydetmek için çağrısında dır:
using TypedHttp.Example;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHttpClient<JokeService>(
client =>
{
// Set the base address of the named client.
client.BaseAddress = new Uri("https://api.icndb.com/");
// Add a user-agent default request header.
client.DefaultRequestHeaders.UserAgent.ParseAdd("dotnet-docs");
});
services.AddTransient<JokeService>();
})
.Build();
Türe sahip istemci, DI ile geçici olarak kaydedilir. Yukarıdaki kodda, AddHttpClient geçici bir hizmet olarak JokeService kaydolr. Bu kayıt, aşağıdaki işlemleri yapmak için bir fabrika yöntemi kullanır:
HttpClientörneği oluşturun.- örneğini oluşturucuya
JokeServicegeçirmesi için birHttpClientörneği oluşturun.
İpucu
çağrısı AddHttpClient<TClient> hizmeti 'ye TClient IServiceCollection eklemez. Yine de ile açıkça eklemeniz Add{ServiceLifetime} gerekir.
Oluşturulan istemciler
IHttpClientFactory, Yeniden Sığdır gibi üçüncü taraf kitaplıklarla birlikte kullanılabilir. Yeniden sığdır, .NET için bir REST kitaplığıdır. Bildirimli tanımlamalar ve REST API arabirim yöntemlerini uç noktalara eşlemeye olanak sağlar. arabiriminin bir uygulaması, dış HTTP çağrıları yapmak RestService için kullanılarak dinamik olarak HttpClient oluşturulur.
Aşağıdaki türleri göz önünde record yapın:
namespace Shared;
public record IdentifiableJokeValue(
int Id, string Joke);
namespace Shared;
public record ChuckNorrisJoke(
string Type,
IdentifiableJokeValue Value);
Aşağıdaki örnek, NuGet Refit.HttpClientFactory paketine dayandır ve basit bir arabirimdir:
using Refit;
using Shared;
namespace GeneratedHttp.Example;
public interface IJokeService
{
[Get("/jokes/random?limitTo=[nerdy]")]
Task<ChuckNorrisJoke> GetRandomJokeAsync();
}
Yukarıdaki C# arabirimi:
- Bir örneği döndüren
GetRandomJokeAsyncadlı bir yöntemiTask<ChuckNorrisJoke>tanımlar. - Dış
Refit.GetAttributeAPI'ye yol ve sorgu dizesi içeren bir öznitelik belirtir.
Türü oluşturulan bir istemci, uygulama oluşturmak için Yeniden Sığdır kullanılarak eklenebilir:
using GeneratedHttp.Example;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Refit;
using Shared;
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddRefitClient<IJokeService>()
.ConfigureHttpClient(client =>
{
// Set the base address of the named client.
client.BaseAddress = new Uri("https://api.icndb.com/");
// Add a user-agent default request header.
client.DefaultRequestHeaders.UserAgent.ParseAdd("dotnet-docs");
});
})
.Build();
Tanımlanan arabirim gerektiğinde DI ve Refit tarafından sağlanan uygulamayla birlikte kullanılabilir.
POST, PUT ve DELETE istekleri yapma
Yukarıdaki örneklerde, tüm HTTP istekleri GET HTTP fiilini kullanır. HttpClient aşağıdakiler dahil olmak üzere diğer HTTP fiillerini de destekler:
- POST
- PUT
- DELETE
- YAMA
Desteklenen HTTP fiillerinin tam listesi için bkz. HttpMethod .
Aşağıdaki örnek, bir HTTP POST isteğinin nasıl yapılacağını göstermektedir:
public async Task CreateItemAsync(Item item)
{
using StringContent json = new(
JsonSerializer.Serialize(item, DefaultJsonSerialization.Options),
Encoding.UTF8,
MediaTypeNames.Application.Json);
using HttpResponseMessage httpResponse =
await _httpClient.PostAsync("/api/items", json);
httpResponse.EnsureSuccessStatusCode();
}
Yukarıdaki kodda, CreateItemAsync yöntemi:
ItemParametresini kullanarak JSON için parametreyi seri hale getirirSystem.Text.Json. Bu JsonSerializerOptions , serileştirme işlemini yapılandırmak için bir örneğini kullanır.- StringContentHttp isteğinin gövdesinde göndermek üzere seri hale GETIRILMIŞ JSON paketini paketlemek için bir örneği oluşturur.
- PostAsyncJSON içeriğini BELIRTILEN URL 'ye göndermek için çağrılar. Bu, HttpClient. BaseAddress'e eklenen GÖRELI bir URL 'dir.
- EnsureSuccessStatusCodeYanıt durum kodu başarıyı belirtmezse bir özel durum oluşturmak için çağırır.
HttpClient , diğer içerik türlerini de destekler. Örneğin MultipartContent ve StreamContent. Desteklenen içeriğin tamamı listesi için bkz HttpContent ..
Aşağıdaki örnekte bir HTTP PUT isteği gösterilmektedir:
public async Task UpdateItemAsync(Item item)
{
using StringContent json = new(
JsonSerializer.Serialize(item, DefaultJsonSerialization.Options),
Encoding.UTF8,
MediaTypeNames.Application.Json);
using HttpResponseMessage httpResponse =
await _httpClient.PutAsync($"/api/items/{item.Id}", json);
httpResponse.EnsureSuccessStatusCode();
}
Yukarıdaki kod, POST örneğine çok benzer. UpdateItemAsyncYöntemi yerine çağırır PutAsync PostAsync .
Aşağıdaki örnekte bir HTTP SILME isteği gösterilmektedir:
public async Task DeleteItemAsync(Guid id)
{
using HttpResponseMessage httpResponse =
await _httpClient.DeleteAsync($"/api/items/{id}");
httpResponse.EnsureSuccessStatusCode();
}
Yukarıdaki kodda, DeleteItemAsync yöntemi çağırır DeleteAsync . HTTP DELETE istekleri genellikle gövde içermediğinden, DeleteAsync yöntemi bir örneğini kabul eden bir aşırı yükleme sağlamaz HttpContent .
İle farklı HTTP fiillerini kullanma hakkında daha fazla bilgi için HttpClient bkz HttpClient ..
HttpClient ömür yönetimi
HttpClientHer çağrıldığında yeni bir örnek döndürülür CreateClient IHttpClientFactory . HttpClientHandlerİstemci başına bir örnek oluşturulur. Fabrika, örneklerin yaşam sürelerini yönetir HttpClientHandler .
IHttpClientFactory``HttpClientHandlerkaynak tüketimini azaltmak için fabrika tarafından oluşturulan örnekleri havuzlar. Bir HttpClientHandler örnek, süresi dolmamışsa yeni bir örnek oluştururken havuzdan yeniden kullanılabilir HttpClient .
Her işleyici genellikle kendi temel aldığı HTTP bağlantısını yönettiğinden işleyicileri havuza alma işlemi tercih edilir. Gerekenden daha fazla işleyici oluşturulması bağlantı gecikmeleri oluşmasına neden olabilir. Ayrıca, bazı işleyiciler bağlantıları süresiz olarak açık tutar, bu da işleyicinin DNS değişikliklerine yeniden davranmasını engelleyebilir.
Varsayılan işleyici ömrü iki dakikadır. Varsayılan değeri geçersiz kılmak için, SetHandlerLifetime her istemci için çağrısı IServiceCollection :
services.AddHttpClient("Named.Client")
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
Önemli
Genellikle HttpClient örnekleri, elden çıkarma gerektirmeyen nesneler olarak değerlendirin. Çıkarma giden istekleri iptal eder ve HttpClient çağırma sonrasında verilen örneğin kullanılamaz olmasını sağlar Dispose . IHttpClientFactory örnekler tarafından kullanılan kaynakları izler ve ortadan kaldırdık HttpClient .
Tek HttpClient bir örneğinin uzun süre canlı tutulması, önünde kullanılmadan önce kullanılan ortak bir modeldir IHttpClientFactory . Bu model, ' a geçtikten sonra gereksiz hale gelir IHttpClientFactory .
Yapılandırma HttpMessageHandler
İstemci tarafından kullanılan iç yapılandırmayı denetlemek gerekli olabilir HttpMessageHandler .
IHttpClientBuilderAdlandırılmış veya yazılan istemciler eklenirken bir döndürülür. ConfigurePrimaryHttpMessageHandlerUzantı yöntemi, üzerinde bir temsilci tanımlamak için kullanılabilir IServiceCollection . Temsilci, HttpMessageHandler Bu istemci tarafından kullanılan birincili oluşturmak ve yapılandırmak için kullanılır:
services.AddHttpClient("Named.Client")
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new HttpClientHandler
{
AllowAutoRedirect = false,
UseDefaultCredentials = true
};
});
Ek yapılandırma
' İ denetlemek için birkaç ek yapılandırma seçeneği vardır IHttpClientHandler :
| Yöntem | Açıklama |
|---|---|
| AddHttpMessageHandler | Adlandırılmış için ek bir ileti işleyicisi ekler HttpClient . |
| AddTypedClient | TClient HttpClient İle ilişkilendirilen ile ilişkili arasındaki bağlamayı yapılandırır IHttpClientBuilder . |
| ConfigureHttpClient | Adlandırılmış bir adı yapılandırmak için kullanılacak bir temsilci ekler HttpClient . |
| ConfigureHttpMessageHandlerBuilder | Adlandırılmış bir için kullanarak ileti işleyicilerini yapılandırmak için kullanılacak bir temsilci ekler HttpMessageHandlerBuilder HttpClient . |
| ConfigurePrimaryHttpMessageHandler | HttpMessageHandlerAdlandırılmış için bağımlılık ekleme kapsayıcısından birincili yapılandırır HttpClient . |
| RedactLoggedHeaders | Günlüğe kaydedilmeden önce değerlerin redaksiyonu gereken HTTP üst bilgi adları koleksiyonunu ayarlar. |
| SetHandlerLifetime | Bir örneğin yeniden kullanılabilir olduğu sürenin uzunluğunu ayarlar HttpMessageHandler . Her bir adlandırılmış istemcinin kendi yapılandırılmış işleyici yaşam süresi değeri olabilir. |