Ce face HttpClient (GetFromJsonAsync)
Clasa System.Net.Http.HttpClient este clientul modern din .NET pentru comunicarea prin HTTP/1.1, HTTP/2 și HTTP/3 cu servicii REST și microservicii externe. Începând cu .NET 5, spațiul de nume System.Net.Http.Json este inclus nativ și adaugă metodele de extensie GetFromJsonAsync<T>, PostAsJsonAsync și PutAsJsonAsync, care combină într-o singură linie apelul de rețea în flux (streaming) și serializarea/deserializarea cu JsonSerializer.
O regulă de arhitectură esențială în .NET: HttpClient este conceput să fie reutilizat pe toată durata de viață a aplicației (sau gestionat prin IHttpClientFactory în ASP.NET Core), nu recreat în blocuri using (var client = new HttpClient()) la fiecare cerere — recrearea repetată epuizează porturile TCP locale (socket exhaustion în starea TIME_WAIT) și pierde cache-ul conexiunilor.
Parametri, metode și opțiuni
| Parametru / Metodă | Descriere |
|---|---|
client.GetFromJsonAsync<T>(url, ct) |
Trimite o cerere GET, verifică statusul 2xx și deserializează fluxul JSON direct în tipul T. |
client.PostAsJsonAsync(url, value, ct) |
Serializează obiectul value ca JSON (application/json) și îl trimite printr-o cerere POST. |
client.GetAsync(url) / SendAsync(req) |
Trimite o cerere HTTP și returnează obiectul complet HttpResponseMessage (antete, cod de status, conținut). |
response.EnsureSuccessStatusCode() |
Aruncă HttpRequestException dacă codul de status HTTP nu este în intervalul 200–299. |
client.BaseAddress / Timeout |
Setează URL-ul de bază pentru cererile relative și durata maximă de așteptare (implicit 100 secunde). |
Exemple
Exemplul 1: Citirea și deserializarea unui API JSON cu GetFromJsonAsync
Folosim o singură instanță statică HttpClient și metoda GetFromJsonAsync<T> pentru a obține direct un obiect C# puternic tipizat.
using System.Net;
using System.Net.Http.Json;
// În aplicații reale: static readonly HttpClient Client = new() { BaseAddress = new Uri("https://api.dexblog.ro") };
using var client = new HttpClient(new HandlerDemo())
{
BaseAddress = new Uri("https://api.dexblog.ro/")
};
CursValutarDto? curs = await client.GetFromJsonAsync<CursValutarDto>("v1/curs/eur");
Console.WriteLine($"Monedă: {curs?.Moneda} | Curs BNR: {curs?.Valoare:F4} RON | Data: {curs?.Data}");
public record CursValutarDto(string Moneda, decimal Valoare, string Data);
// Handler local doar pentru ca exemplul să ruleze determinist fără acces extern la internet:
file sealed class HandlerDemo : HttpMessageHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage req, CancellationToken ct) =>
Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
{
Content = JsonContent.Create(new { moneda = "EUR", valoare = 4.9765m, data = "2026-10-23" })
});
}
Ieșire în consolă
Monedă: EUR | Curs BNR: 4.9765 RON | Data: 2026-10-23
Exemplul 2: Trimiterea unui payload cu PostAsJsonAsync și verificarea răspunsului
Trimitem un obiect printr-o cerere POST, verificăm statusul HTTP cu IsSuccessStatusCode și citim corpul răspunsului.
using System.Net;
using System.Net.Http.Json;
using var client = new HttpClient(new HandlerPostDemo());
var comandaNoua = new { ClientId = 105, ProdusSku = "SSD-1TB", Cantitate = 2 };
using HttpResponseMessage raspuns = await client.PostAsJsonAsync("https://api.dexblog.ro/v1/comenzi", comandaNoua);
raspuns.EnsureSuccessStatusCode();
var confirmare = await raspuns.Content.ReadFromJsonAsync<ConfirmareComanda>();
Console.WriteLine($"Status HTTP: {(int)raspuns.StatusCode} ({raspuns.StatusCode}) -> ID Comandă: {confirmare?.ComandaId}");
public record ConfirmareComanda(int ComandaId, string Status);
file sealed class HandlerPostDemo : HttpMessageHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage req, CancellationToken ct) =>
Task.FromResult(new HttpResponseMessage(HttpStatusCode.Created)
{
Content = JsonContent.Create(new { comandaId = 9081, status = "InProcesare" })
});
}
Ieșire în consolă
Status HTTP: 201 (Created) -> ID Comandă: 9081
Greșeli frecvente
- Instanțierea
using var client = new HttpClient();în interiorul unei metode apelate de sute de ori pe secundă — chiar dacăHttpClientimplementeazăIDisposable, închiderea lui nu eliberează imediat socket-ul TCP din sistemul de operare, ducând laSocketExceptionsub trafic intens. FoloseșteIHttpClientFactory(builder.Services.AddHttpClient()) sau o instanțăstatic readonly HttpClientcuPooledConnectionLifetimesetat. - Citirea întregului răspuns într-un
stringcuawait response.Content.ReadAsStringAsync()urmată deJsonSerializer.Deserialize— folosește directGetFromJsonAsyncsauReadFromJsonAsync, care deserializează direct din fluxul de rețea fără a aloca un șir uriaș în memorie.
Funcții și concepte înrudite
JsonSerializer (System.Text.Json): Serializează obiecte C# în format JSON și deserializează text JSON înapoi în tipuri puternic tipizate, cu performanță nativă ridicată.async / await și Task<T>: Execută operațiuni I/O neblocante (rețea, baze de date, fișiere) și coordonează sarcini concurente cu Task și Task.WhenAll.try / catch și using (IDisposable): Gestionează controlat excepțiile la rulare și eliberează garantat resursele externe (fișiere, conexiuni, stream-uri) prin IDisposable.