Volání webového rozhraní API z klienta .NET (C#)
Tento obsah je určený pro předchozí verzi rozhraní .NET. Nový vývoj by měl používat ASP.NET Core. Další informace o používání webového rozhraní API ASP.NET Core najdete tady:
Stáhněte si dokončený projekt.
V tomto kurzu se dozvíte, jak volat webové rozhraní API z aplikace .NET pomocí System.Net.Http.HttpClient.
V tomto kurzu je napsána klientská aplikace, která využívá následující webové rozhraní API:
Akce | Metoda HTTP | Relativní identifikátor URI |
---|---|---|
Získání produktu podle ID | GET | /api/products/id |
Vytvoření nového produktu | POST | /api/products |
Aktualizace produktu | PUT | /api/products/id |
Odstranění produktu | DELETE | /api/products/id |
Informace o implementaci tohoto rozhraní API s webovým rozhraním API ASP.NET najdete v tématu Vytvoření webového rozhraní API, které podporuje operace CRUD.
Pro zjednodušení je klientskou aplikací v tomto kurzu konzolová aplikace systému Windows. HttpClient je také podporován pro Windows Phone a aplikace pro Windows Store. Další informace najdete v tématu Psaní kódu klienta webového rozhraní API pro více platforem pomocí přenosných knihoven.
POZNÁMKA: Pokud předáváte základní adresy URL a relativní identifikátory URI jako pevně zakódované hodnoty, mějte na paměti pravidla pro využití HttpClient
rozhraní API. Vlastnost HttpClient.BaseAddress
by měla být nastavená na adresu s koncovým lomítkem (/
). Například při předávání pevně zakódovaných identifikátorů URI prostředků metodě HttpClient.GetAsync
nezahrnujte počáteční lomítko. Získání Product
id podle:
- Nastavit
client.BaseAddress = new Uri("https://localhost:5001/");
- Vyžádejte si .
Product
Například,client.GetAsync<Product>("api/products/4");
.
Vytvoření konzolové aplikace
V sadě Visual Studio vytvořte novou konzolovou aplikaci pro Windows s názvem HttpClientSample a vložte následující kód:
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace HttpClientSample
{
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
class Program
{
static HttpClient client = new HttpClient();
static void ShowProduct(Product product)
{
Console.WriteLine($"Name: {product.Name}\tPrice: " +
$"{product.Price}\tCategory: {product.Category}");
}
static async Task<Uri> CreateProductAsync(Product product)
{
HttpResponseMessage response = await client.PostAsJsonAsync(
"api/products", product);
response.EnsureSuccessStatusCode();
// return URI of the created resource.
return response.Headers.Location;
}
static async Task<Product> GetProductAsync(string path)
{
Product product = null;
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
product = await response.Content.ReadAsAsync<Product>();
}
return product;
}
static async Task<Product> UpdateProductAsync(Product product)
{
HttpResponseMessage response = await client.PutAsJsonAsync(
$"api/products/{product.Id}", product);
response.EnsureSuccessStatusCode();
// Deserialize the updated product from the response body.
product = await response.Content.ReadAsAsync<Product>();
return product;
}
static async Task<HttpStatusCode> DeleteProductAsync(string id)
{
HttpResponseMessage response = await client.DeleteAsync(
$"api/products/{id}");
return response.StatusCode;
}
static void Main()
{
RunAsync().GetAwaiter().GetResult();
}
static async Task RunAsync()
{
// Update port # in the following line.
client.BaseAddress = new Uri("http://localhost:64195/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
try
{
// Create a new product
Product product = new Product
{
Name = "Gizmo",
Price = 100,
Category = "Widgets"
};
var url = await CreateProductAsync(product);
Console.WriteLine($"Created at {url}");
// Get the product
product = await GetProductAsync(url.PathAndQuery);
ShowProduct(product);
// Update the product
Console.WriteLine("Updating price...");
product.Price = 80;
await UpdateProductAsync(product);
// Get the updated product
product = await GetProductAsync(url.PathAndQuery);
ShowProduct(product);
// Delete the product
var statusCode = await DeleteProductAsync(product.Id);
Console.WriteLine($"Deleted (HTTP Status = {(int)statusCode})");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadLine();
}
}
}
Předchozí kód je kompletní klientská aplikace.
RunAsync
se spustí a zablokuje, dokud se to neskonče. Většina metod HttpClient je asynchronní, protože provádějí síťové vstupně-výstupní operace. Všechny asynchronní úlohy se provádějí uvnitř RunAsync
. Aplikace obvykle neblokuje hlavní vlákno, ale tato aplikace neumožňuje žádnou interakci.
static async Task RunAsync()
{
// Update port # in the following line.
client.BaseAddress = new Uri("http://localhost:64195/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
try
{
// Create a new product
Product product = new Product
{
Name = "Gizmo",
Price = 100,
Category = "Widgets"
};
var url = await CreateProductAsync(product);
Console.WriteLine($"Created at {url}");
// Get the product
product = await GetProductAsync(url.PathAndQuery);
ShowProduct(product);
// Update the product
Console.WriteLine("Updating price...");
product.Price = 80;
await UpdateProductAsync(product);
// Get the updated product
product = await GetProductAsync(url.PathAndQuery);
ShowProduct(product);
// Delete the product
var statusCode = await DeleteProductAsync(product.Id);
Console.WriteLine($"Deleted (HTTP Status = {(int)statusCode})");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadLine();
}
Instalace klientských knihoven webového rozhraní API
Pomocí Správce balíčků NuGet nainstalujte balíček klientských knihoven webového rozhraní API.
V nabídce Nástroje vyberteKonzola Správce>balíčků NuGet. V konzole Správce balíčků (PMC) zadejte následující příkaz:
Install-Package Microsoft.AspNet.WebApi.Client
Předchozí příkaz přidá do projektu následující balíčky NuGet:
- Microsoft.AspNet.WebApi.Client
- Newtonsoft.Json
Newtonsoft.Json (označovaný také jako Json.NET) je oblíbená vysoce výkonná architektura JSON pro .NET.
Přidání třídy modelu
Product
Prozkoumejte třídu:
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
Tato třída odpovídá datovému modelu používanému webovým rozhraním API. Aplikace může použít HttpClient ke čtení Product
instance z odpovědi HTTP. Aplikace nemusí psát žádný deserializační kód.
Vytvoření a inicializace HttpClient
Prozkoumejte statickou vlastnost HttpClient :
static HttpClient client = new HttpClient();
Cílem httpClient je vytvořit instanci jednou a opakovaně používat po celou dobu životnosti aplikace. Následující podmínky můžou vést k chybám SocketException :
- Vytvoření nové instance HttpClient pro každý požadavek
- Server s velkým zatížením.
Vytvoření nové instance HttpClient na požadavek může vyčerpat dostupné sokety.
Následující kód inicializuje instanci HttpClient :
static async Task RunAsync()
{
// Update port # in the following line.
client.BaseAddress = new Uri("http://localhost:64195/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
Předchozí kód:
- Nastaví základní identifikátor URI pro požadavky HTTP. Změňte číslo portu na port použitý v serverové aplikaci. Aplikace nebude fungovat, pokud se nepoužije port pro serverové aplikace.
- Nastaví hlavičku Accept na application/json. Nastavení této hlavičky informuje server, aby odesílal data ve formátu JSON.
Odeslání požadavku GET pro načtení prostředku
Následující kód odešle požadavek GET pro produkt:
static async Task<Product> GetProductAsync(string path)
{
Product product = null;
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
product = await response.Content.ReadAsAsync<Product>();
}
return product;
}
Metoda GetAsync odešle požadavek HTTP GET. Po dokončení metody vrátí HttpResponseMessage , která obsahuje odpověď HTTP. Pokud je stavovým kódem v odpovědi kód úspěchu, tělo odpovědi obsahuje reprezentaci produktu ve formátu JSON. Volání readAsAsync k deserializaci datové části JSON na Product
instanci. Metoda ReadAsAsync je asynchronní, protože tělo odpovědi může být libovolně velké.
HttpClient nevyvolá výjimku, pokud odpověď HTTP obsahuje kód chyby. Místo toho isSuccessStatusCode vlastnost je false , pokud je stav kód chyby. Pokud chcete kódy chyb HTTP považovat za výjimky, zavolejte httpResponseMessage.EnsureSuccessStatusCode objekt odpovědi . EnsureSuccessStatusCode
vyvolá výjimku, pokud stavový kód spadá mimo rozsah 200–299. Všimněte si, že HttpClient může vyvolat výjimky z jiných důvodů – například pokud vyprší časový limit požadavku.
Media-Type formátovací moduly k deserializaci
Při zavolání ReadAsAsync bez parametrů se používá výchozí sada formátovačů médií ke čtení textu odpovědi. Výchozí formátovací moduly podporují data zakódovaná ve formátu JSON, XML a form-url.
Místo použití výchozích formátovačů můžete poskytnout seznam formátovačů metodě ReadAsAsync . Použití seznamu formátovačů je užitečné, pokud máte vlastní formátovací typ média:
var formatters = new List<MediaTypeFormatter>() {
new MyCustomFormatter(),
new JsonMediaTypeFormatter(),
new XmlMediaTypeFormatter()
};
resp.Content.ReadAsAsync<IEnumerable<Product>>(formatters);
Další informace najdete v tématu Formátování médií ve webovém rozhraní API ASP.NET 2.
Odeslání požadavku POST na vytvoření prostředku
Následující kód odešle požadavek POST, který obsahuje Product
instanci ve formátu JSON:
static async Task<Uri> CreateProductAsync(Product product)
{
HttpResponseMessage response = await client.PostAsJsonAsync(
"api/products", product);
response.EnsureSuccessStatusCode();
// return URI of the created resource.
return response.Headers.Location;
}
Metoda PostAsJsonAsync :
- Serializuje objekt do formátu JSON.
- Odešle datovou část JSON v požadavku POST.
Pokud je požadavek úspěšný:
- Měla by vrátit odpověď 201 (Vytvořeno).
- Odpověď by měla obsahovat adresu URL vytvořených prostředků v záhlaví Umístění.
Odeslání požadavku PUT na aktualizaci prostředku
Následující kód odešle požadavek PUT na aktualizaci produktu:
static async Task<Product> UpdateProductAsync(Product product)
{
HttpResponseMessage response = await client.PutAsJsonAsync(
$"api/products/{product.Id}", product);
response.EnsureSuccessStatusCode();
// Deserialize the updated product from the response body.
product = await response.Content.ReadAsAsync<Product>();
return product;
}
Metoda PutAsJsonAsync funguje podobně jako PostAsJsonAsync s tím rozdílem, že odesílá požadavek PUT místo POST.
Odeslání požadavku DELETE na odstranění prostředku
Následující kód odešle požadavek DELETE na odstranění produktu:
static async Task<HttpStatusCode> DeleteProductAsync(string id)
{
HttpResponseMessage response = await client.DeleteAsync(
$"api/products/{id}");
return response.StatusCode;
}
Podobně jako GET nemá požadavek DELETE text požadavku. Pomocí příkazu DELETE nemusíte zadávat formát JSON nebo XML.
Otestování ukázky
Testování klientské aplikace:
Stáhněte a spusťte serverové aplikace. Ověřte, že serverová aplikace funguje. Měl by například
http://localhost:64195/api/products
vrátit seznam produktů.Nastavte základní identifikátor URI pro požadavky HTTP. Změňte číslo portu na port použitý v serverové aplikaci.
static async Task RunAsync() { // Update port # in the following line. client.BaseAddress = new Uri("http://localhost:64195/"); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json"));
Spusťte klientskou aplikaci. Vytvoří se následující výstup:
Created at http://localhost:64195/api/products/4 Name: Gizmo Price: 100.0 Category: Widgets Updating price... Name: Gizmo Price: 80.0 Category: Widgets Deleted (HTTP Status = 204)