HttpClient (GetFromJsonAsync) în C# (.NET)

.NET BCL și CLI-ul dotnet .NET 4.5+ (GetFromJsonAsync în .NET 5+)

Trimite cereri HTTP asincrone către API-uri REST și deserializează direct răspunsurile JSON cu metodele din System.Net.Http.Json.

Sintaxă C#
var date = await httpClient.GetFromJsonAsync<TDto>("https://api.exemplu.ro/v1/items", ct);

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ă HttpClient implementează IDisposable, închiderea lui nu eliberează imediat socket-ul TCP din sistemul de operare, ducând la SocketException sub trafic intens. Folosește IHttpClientFactory (builder.Services.AddHttpClient()) sau o instanță static readonly HttpClient cu PooledConnectionLifetime setat.
  • Citirea întregului răspuns într-un string cu await response.Content.ReadAsStringAsync() urmată de JsonSerializer.Deserialize — folosește direct GetFromJsonAsync sau ReadFromJsonAsync, 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.