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

Bu içerik.NET'in önceki bir sürümüne yöneliktir. Yeni geliştirme ASP.NET Core kullanmalıdır. ASP.NET Core Web API'sini kullanma hakkında daha fazla bilgi için bkz:

Tamamlanan Projeyi indirin.

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

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
Bir ürünü güncelleştirme PUT /api/products/id
Ürün silme DELETE /api/products/id

Bu API'yi ASP.NET Web API'siyle uygulamayı öğrenmek için bkz. CRUD İşlemlerini Destekleyen Bir Web API'sini Oluşturma.

Kolaylık olması için, bu öğreticideki istemci uygulaması bir Windows konsol uygulamasıdır. HttpClient, Windows Phone ve Windows Mağazası uygulamaları için de desteklenir. Daha fazla bilgi için bkz. Taşınabilir Kitaplıkları Kullanarak Birden Çok Platform için Web API İstemci Kodu Yazma

NOT: Temel URL'leri ve göreli URI'leri sabit kodlanmış değerler olarak geçirirseniz API'yi kullanma HttpClient kurallarına dikkat edin. özelliği, HttpClient.BaseAddress sonunda eğik çizgi ()/ bulunan bir adrese ayarlanmalıdır. Örneğin, sabit kodlanmış kaynak URI'lerini yöntemine HttpClient.GetAsync geçirirken baştaki eğik çizgi eklemeyin. Kimlik bilgilerini almak Product için:

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

Konsol Uygulaması Oluşturma

Visual Studio'da 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 tamamlanana kadar çalıştırılır ve bloklar. Çoğu HttpClient yöntemi, ağ G/Ç'sini gerçekleştirdiğinden zaman uyumsuz olarak gerçekleştirilir. Tüm zaman uyumsuz görevler içinde RunAsyncgerçekleştirilir. 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 İstemci Kitaplıklarını Yükleme

Web API İstemci Kitaplıkları paketini yüklemek için NuGet Paket Yöneticisi'ni kullanın.

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

Install-Package Microsoft.AspNet.WebApi.Client

Yukarıdaki komut aşağıdaki NuGet paketlerini projeye 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'sinin kullandığı veri modeliyle eşleşir. Bir uygulama HTTP yanıtından bir Product örneği okumak için HttpClient kullanabilir. Uygulamanın seri durumdan çıkarma kodu yazması gerekmez.

HttpClient Oluşturma ve Başlatma

Statik HttpClient özelliğini inceleyin:

static HttpClient client = new HttpClient();

HttpClient'ın bir kez örneği oluşturulup 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şturma.
  • Sunucu ağır yük altında.

İstek başına yeni bir HttpClient örneği oluşturmak 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ığı sürece uygulama çalışmaz.
  • Accept üst bilgisini "application/json" olarak ayarlar. Bu üst bilgiyi ayarlamak, sunucuya JSON biçiminde veri göndermesini bildirir.

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ıttaki durum kodu bir başarı koduysa, yanıt gövdesi bir ürünün JSON gösterimini içerir. Bir örneğe JSON yükünü seri durumdan silmek için ReadAsAsync'iProduct çağırın. Yanıt gövdesi rastgele olarak büyük olabileceğinden ReadAsAsync yöntemi zaman uyumsuzdur.

HTTP yanıtı bir hata kodu içerdiğinde HttpClient özel durum oluşturmaz. Bunun yerine, durum bir hata koduysa IsSuccessStatusCode özelliği false olur. HTTP hata kodlarını özel durum olarak ele almak isterseniz, yanıt nesnesinde HttpResponseMessage.EnsureSuccessStatusCode çağrısı yapın. EnsureSuccessStatusCode durum kodu 200–299 aralığının dışında kalırsa bir özel durum oluşturur. HttpClient'ın başka nedenlerle özel durumlar oluşturabileceğini unutmayın; örneğin, istek zaman aşımına uğradıysa.

Seri Durumdan Çıkarma için Biçimlendiricileri Media-Type

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

Varsayılan biçimlendiricileri kullanmak yerine ReadAsAsync yöntemine biçimlendiricilerin listesini sağlayabilirsiniz. Özel bir medya türü biçimlendiriciniz varsa biçimlendirici listesi kullanmak 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. ASP.NET Web API 2'deki Medya Biçimlendiricileri

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

Aşağıdaki kod, JSON biçiminde bir örnek içeren bir Product POST 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'a serileştirir.
  • JSON yükünü bir POST isteğinde gönderir.

İstek başarılı olursa:

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

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ğinin de istek gövdesi yoktur. DELETE ile JSON veya XML biçimi belirtmeniz gerekmez.

Örneği test edin

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

  1. Sunucu uygulamasını indirin ve çalıştırın. Sunucu uygulamasının çalıştığını doğrulayın. Örneğin, http://localhost:64195/api/products bir ürün listesi 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)