.NET İstemciden Web API'si Çağırma (C#)

Mike Wasson ve Rick Anderson

Bu içerik, .NET'in önceki bir sürümüne göredir. Yeni geliştirmede core ASP.NET gerekir. ASP.NET Core Web API'sini kullanma hakkında daha fazla bilgi için bkz:

Tamamlanan Projeyi İndirin. yönergelerini indirin.

Bu öğreticide, System.Net.Http.HttpClient kullanarak bir .NET uygulamasından web API'sini çağırmayı gösterir.

Bu öğreticide, aşağıdaki web API'sini kullanan bir istemci uygulaması yazılır:

Eylem HTTP yöntemi Göreli URI
Kimliğe göre bir ürün alma GET /api/products/id
Yeni ürün oluşturma POST /api/products
Ürünü güncelleştirme PUT /api/products/id
Ürünü silme DELETE /api/products/id

Bu API'yi web API'si ile ASP.NET için bkz. CRUD İşlemlerini Destekleyen Bir Web API'si Oluşturma.

Kolaylık olması için bu öğreticide yer alan istemci uygulaması bir Windows konsol uygulamasıdır. HttpClient, windows mağazası Windows Phone için de de kullanılabilir. Daha fazla bilgi için bkz. Taşınabilir Kitaplıklar Kullanarak Birden Çok Platform için Web API'si İstemci Kodu Yazma

NOT: Temel URL'leri ve göreli URL'leri sabit kodlu değerler olarak iletirsiniz, API'yi kullanma kurallarına dikkat HttpClient edin. özelliği, sonda eğik çizgi ( ) HttpClient.BaseAddress olan bir adrese ayar / gerekir. Örneğin, yöntemine sabit kodlu kaynak HttpClient.GetAsync URL'leri iletirken, baştaki eğik çizgiyi dahil etme. Bir kimliği almak Product için:

  1. Ayarlamak client.BaseAddress = new Uri("https://localhost:5001/");
  2. bir Product isteği. Örneğin, client.GetAsync<Product>("api/products/4");.

Konsol Uygulaması Oluşturma

Bu Visual Studio HttpClientSample adlı yeni bir Windows konsol uygulaması oluşturun ve aşağıdaki kodu yapıştırın:

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();
        }
    }
}

Yukarıdaki kod, tam istemci uygulamasıdır.

RunAsync çalışan ve blokları tamamlayana kadar çalıştırır. Çoğu HttpClient yöntemi, ağ G/Ç gerçekleştirecekleri için zaman uyumsuz olur. Zaman uyumsuz görevlerin hepsi içinde RunAsync yapılır. Normalde bir uygulama ana iş parçacığını engellemez, ancak bu uygulama herhangi bir etkileşime izin vermez.

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();
}

Web API'si İstemci Kitaplıklarını Yükleme

Web API Paket Yöneticisi paketini yüklemek için NuGet Paket Yöneticisi'yi kullanın.

Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu' nu seçin. Paket Yöneticisi konsolunda (PMC), aşağıdaki komutu yazın:

Install-Package Microsoft.AspNet.WebApi.Client

Yukarıdaki komut, projeye aşağıdaki NuGet paketlerini ekler:

  • Microsoft. AspNet. WebApi. Client
  • Newtonsoft.Json

Newtonsoft.Json (Json.NET olarak da bilinir), .NET için popüler bir yüksek performanslı JSON çerçevesidir.

Model sınıfı ekleme

Sınıfı inceleyin Product :

public class Product
{
    public string Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string Category { get; set; }
}

Bu sınıf, Web API 'SI tarafından kullanılan veri modeliyle eşleşir. Bir uygulama, HTTP yanıtından bir örnek okumak için HttpClient kullanabilir Product . Uygulamanın seri durumdan çıkarma kodu yazmak zorunda değildir.

HttpClient oluşturma ve başlatma

Statik HttpClient özelliğini inceleyin:

static HttpClient client = new HttpClient();

HttpClient uygulamasının bir kez oluşturulması ve bir uygulamanın ömrü boyunca yeniden kullanılması amaçlanmıştır. Aşağıdaki koşullar, SocketException hatalarına neden olabilir:

  • İstek başına yeni bir HttpClient örneği oluşturuluyor.
  • Sunucu ağır yük altında.

Her istek için yeni bir HttpClient örneği oluşturulması, kullanılabilir yuvaları tüketebilir.

Aşağıdaki kod, HttpClient örneğini başlatır:

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"));

Yukarıdaki kod:

  • HTTP istekleri için temel URI 'yi ayarlar. Bağlantı noktası numarasını sunucu uygulamasında kullanılan bağlantı noktasıyla değiştirin. Sunucu uygulaması için bağlantı noktası kullanılmadıkça uygulama çalışmaz.
  • Accept üst bilgilerini "application/json" olarak ayarlar. Bu üst bilgi ayarlanırken sunucuya JSON biçiminde veri göndermesi gerekir.

Kaynak almak için GET isteği gönderme

Aşağıdaki kod, bir ürün için bir GET isteği gönderir:

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;
}

GetAsync yöntemi HTTP GET isteğini gönderir. Yöntem tamamlandığında, HTTP yanıtını içeren bir HttpResponseMessage döndürür. Yanıtta durum kodu bir başarı kodu ise, yanıt gövdesi bir ürünün JSON gösterimini içerir. JSON yükünü bir örnek için deserialize için ReadAsAsync Product çağrısı. Yanıt gövdesi rastgele büyük olduğundan ReadAsAsync yöntemi zaman uyumsuzdur.

HTTP yanıtı bir hata kodu içerdiğinde HttpClient bir özel durum oluşturur. Bunun yerine, durum bir hata kodu ise IsSuccessStatusCode özelliği false olur. HTTP hata kodlarını özel durum olarak işlemeyi tercih ederseniz, yanıt nesnede HttpResponseMessage.EnsureSuccessStatusCode'u arayın. EnsureSuccessStatusCode durum kodu 200 299 aralığının dışında olursa bir – özel durum oluşturur. HttpClient'ın, istek zaman dışı olduğu durumlar — gibi başka nedenlerle özel durumlar da atabiliyor.

Media-Type Için Biçimlendirilmişler

ReadAsAsync parametresiz çağrıldı olduğunda, yanıt gövdesini okumak için varsayılan bir medya biçimlendiren kümesi kullanır. Varsayılan biçimlendirenler JSON, XML ve Form-url ile kodlanmış verileri destekler.

Varsayılan biçimlendirenleri kullanmak yerine ReadAsAsync yöntemine biçimlendirenlerin listesini sebilirsiniz. Biçimlendirenler listesi kullanmak, özel bir medya türü biçimlendirıcıya sahip olursanız yararlıdır:

var formatters = new List<MediaTypeFormatter>() {
    new MyCustomFormatter(),
    new JsonMediaTypeFormatter(),
    new XmlMediaTypeFormatter()
};
resp.Content.ReadAsAsync<IEnumerable<Product>>(formatters);

Daha fazla bilgi için bkz. Web API 2'de ASP.NET Biçimlendirenler

Kaynak Oluşturmak için POST İsteği Gönderme

Aşağıdaki kod, JSON biçiminde bir örnek içeren bir POST Product isteği gönderir:

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;
}

PostAsJsonAsync yöntemi:

  • Bir nesneyi JSON olarak seri hale getirme.
  • Post isteğinde JSON yükünü gönderir.

İstek başarılı olursa:

  • Bir 201 (Oluşturuldu) yanıtı dönüşletir.
  • Yanıt, Konum üst bilgisinde oluşturulan kaynakların URL'sini içermesi gerekir.

Kaynağı Güncelleştirmek için PUT İsteği Gönderme

Aşağıdaki kod, bir ürünü güncelleştirmek için bir PUT isteği gönderir:

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;
}

PutAsJsonAsync yöntemi PostAsJsonAsync gibi çalışır, ancak POST yerine PUT isteği gönderir.

Kaynağı Silmek için DELETE İsteği Gönderme

Aşağıdaki kod, bir ürünü silmek için bir DELETE isteği gönderir:

static async Task<HttpStatusCode> DeleteProductAsync(string id)
{
    HttpResponseMessage response = await client.DeleteAsync(
        $"api/products/{id}");
    return response.StatusCode;
}

GET gibi DELETE isteği de istek gövdesine sahip değildir. DELETE ile JSON veya XML biçimi belirtmenize gerek yok.

Örneği test etmek

İstemci uygulamasını test etmek için:

  1. Sunucu uygulamasını indirin ve çalıştırın. yönergelerini indirin. Sunucu uygulamasının çalıştığını doğrulayın. Örneğin, http://localhost:64195/api/products ürünlerin bir listesini döndürmelidir.

  2. HTTP istekleri için temel URI 'yi ayarlayın. Bağlantı noktası numarasını sunucu uygulamasında kullanılan bağlantı noktasıyla değiştirin.

    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"));
    
  3. İstemci uygulamasını çalıştırın. Aşağıdaki çıktı üretilir:

    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)