Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo contenuto riguarda una versione precedente di .NET. Il nuovo sviluppo deve usare ASP.NET Core. Per altre informazioni sull'uso dell'API Web di ASP.NET Core, vedere:
Scaricare il progetto completato.
Questa esercitazione illustra come chiamare un'API Web da un'applicazione .NET usando System.Net.Http.HttpClient.
In questa esercitazione viene scritta un'app client che usa l'API Web seguente:
| Action | Metodo HTTP | URI relativo |
|---|---|---|
| Ottenere un prodotto in base all'ID | GET | /api/products/id |
| Creare un nuovo prodotto | POST | /api/products |
| Aggiornare un prodotto | PUT | /api/products/id |
| Eliminare un prodotto | DELETE | /api/products/id |
Per informazioni su come implementare questa API con ASP.NET API Web, vedere Creazione di un'API Web che supporta operazioni CRUD.
Per semplicità, l'applicazione client in questa esercitazione è un'applicazione console di Windows. HttpClient è supportato anche per le app di Windows Phone e Windows Store. Per altre informazioni, vedere Scrittura di codice client API Web per più piattaforme tramite librerie portabili
NOTA: Se si passano gli URL di base e gli URI relativi come valori hard-coded, tenere presente le regole per l'utilizzo dell'API HttpClient. La HttpClient.BaseAddress proprietà deve essere impostata su un indirizzo con una barra finale (/). Ad esempio, quando si passano URI di risorse hard-coded al metodo HttpClient.GetAsync, non includere una barra diagonale iniziale. Per ottenere un id Product :
- Impostare
client.BaseAddress = new Uri("https://localhost:5001/"); - Richiedere un
Product. Ad esempio:client.GetAsync<Product>("api/products/4");.
Creare l'applicazione console
In Visual Studio creare una nuova app console di Windows denominata HttpClientSample e incollarla nel codice seguente:
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();
}
}
}
Il codice precedente è l'app client completa.
RunAsync viene eseguito e resta bloccato fino al completamento. La maggior parte dei metodi HttpClient è asincrona , perché esegue operazioni di I/O di rete. Tutte le attività asincrone vengono eseguite all'interno di RunAsync. In genere un'app non blocca il thread principale, ma questa app non consente alcuna interazione.
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();
}
Installare le librerie client dell'API Web
Usare il Gestore pacchetti NuGet per installare il pacchetto librerie client per API Web.
Dal menu Tools selezionare NuGet Package Manager>Package Manager Console. Nella console di Gestione pacchetti digitare il comando seguente:
Install-Package Microsoft.AspNet.WebApi.Client
Il comando precedente aggiunge i pacchetti NuGet seguenti al progetto:
- Microsoft.AspNet.WebApi.Client
- Newtonsoft.Json
Newtonsoft.Json (noto anche come Json.NET) è un popolare framework JSON ad alte prestazioni per .NET.
Aggiungere una classe modello
Esaminare la Product classe :
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
Questa classe corrisponde al modello di dati usato dall'API Web. Un'app può usare HttpClient per leggere un'istanza Product da una risposta HTTP. L'app non deve scrivere codice di deserializzazione.
Creare e inizializzare HttpClient
Esaminare la proprietà statica HttpClient :
static HttpClient client = new HttpClient();
HttpClient deve essere creata un'istanza una sola volta e riutilizzata per tutta la durata di un'applicazione. Le condizioni seguenti possono causare errori SocketException :
- Creazione di una nuova istanza HttpClient per richiesta.
- Server sottoposto a carico elevato.
La creazione di una nuova istanza HttpClient per richiesta può esaurire i socket disponibili.
Il codice seguente inizializza l'istanza 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"));
Il codice precedente:
- Imposta l'URI di base per le richieste HTTP. Modificare il numero di porta con il numero usato nell'app server. L'app non funzionerà a meno che non venga usata la porta per l'app server.
- Imposta l'intestazione Accept su "application/json". L'impostazione di questa intestazione indica al server di inviare dati in formato JSON.
Inviare una richiesta GET per recuperare una risorsa
Il codice seguente invia una richiesta GET per un prodotto:
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;
}
Il metodo GetAsync invia la richiesta HTTP GET. Al termine del metodo, restituisce un httpResponseMessage che contiene la risposta HTTP. Se il codice di stato nella risposta è un codice di esito positivo, il corpo della risposta contiene la rappresentazione JSON di un prodotto. Chiamare ReadAsAsync per deserializzare il payload JSON in un'istanza di Product. Il metodo ReadAsAsync è asincrono perché il corpo della risposta può essere arbitrariamente grande.
HttpClient non genera un'eccezione quando la risposta HTTP contiene un codice di errore. Al contrario, la proprietà IsSuccessStatusCode è false se lo stato è un codice di errore. Se si preferisce considerare i codici di errore HTTP come eccezioni, chiamare HttpResponseMessage.EnsureSuccessStatusCode nell'oggetto risposta.
EnsureSuccessStatusCode genera un'eccezione se il codice di stato non rientra nell'intervallo da 200 a 299. Si noti che HttpClient può generare eccezioni per altri motivi, ad esempio se la richiesta scade.
Formattatori di tipo media per deserializzare
Quando ReadAsAsync viene chiamato senza parametri, usa un set predefinito di formattatori multimediali per leggere il corpo della risposta. I formattatori predefiniti supportano i dati con codifica JSON, XML e Form-url.
Anziché usare i formattatori predefiniti, è possibile fornire un elenco di formattatori al metodo ReadAsAsync . L'uso di un elenco di formattatori è utile se si dispone di un formattatore di tipo multimediale personalizzato:
var formatters = new List<MediaTypeFormatter>() {
new MyCustomFormatter(),
new JsonMediaTypeFormatter(),
new XmlMediaTypeFormatter()
};
resp.Content.ReadAsAsync<IEnumerable<Product>>(formatters);
Per altre informazioni, vedere Formattatori multimediali in ASP.NET API Web 2
Invio di una richiesta POST per creare una risorsa
Il codice seguente invia una richiesta POST che contiene un'istanza Product in formato 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;
}
Metodo PostAsJsonAsync :
- Serializza un oggetto in JSON.
- Invia il payload JSON in una richiesta POST.
Se la richiesta ha esito positivo:
- Deve restituire una risposta 201 (creata).
- La risposta deve includere l'URL delle risorse create nell'intestazione Location.
Invio di una richiesta PUT per aggiornare una risorsa
Il codice seguente invia una richiesta PUT per aggiornare un prodotto:
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;
}
Il metodo PutAsJsonAsync funziona come PostAsJsonAsync, ad eccezione del fatto che invia una richiesta PUT anziché POST.
Invio di una richiesta DELETE per eliminare una risorsa
Il codice seguente invia una richiesta DELETE per eliminare un prodotto:
static async Task<HttpStatusCode> DeleteProductAsync(string id)
{
HttpResponseMessage response = await client.DeleteAsync(
$"api/products/{id}");
return response.StatusCode;
}
Analogamente a GET, una richiesta DELETE non ha un corpo della richiesta. Non è necessario specificare il formato JSON o XML con DELETE.
Testare l'esempio
Per testare l'app client:
Scaricare ed eseguire l'app server. Verificare che l'app server funzioni. Ad esempio,
http://localhost:64195/api/productsdeve restituire un elenco di prodotti.Impostare l'URI di base per le richieste HTTP. Modificare il numero di porta con quello utilizzato nell'app server.
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"));Esegui l'applicazione client. Viene prodotto l'output seguente:
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)