HttpClient ve WebClient arasında karar verme


218

Web uygulamamız .Net Framework 4.0'da çalışıyor. Kullanıcı arayüzü denetleyici yöntemlerini ajax çağrıları aracılığıyla çağırır.

REST servisini tedarikçimizden tüketmemiz gerekiyor. .Net 4.0'da REST hizmetini çağırmanın en iyi yolunu değerlendiriyorum. REST hizmeti Temel Kimlik Doğrulama Düzeni gerektirir ve hem XML hem de JSON'da veri döndürebilir. Büyük veri yükleme / indirme zorunluluğu yoktur ve gelecekte hiçbir şey göremiyorum. REST tüketimi için birkaç açık kaynak kodlu projeye baktım ve projede ek bağımlılığı haklı çıkaracak herhangi bir değer bulamadım. Değerlendirmeye başladı WebClientve HttpClient. NuGet'ten .Net 4.0 için HttpClient'i indirdim.

Ben arasındaki farkların aramış WebClientve HttpClientve bu site bu tek HttpClient işleyebilir eşzamanlı aramalar söz ve DNS, çerez yapılandırma ve kimlik çözüldü yeniden kullanabilirsiniz. Farklılıklar nedeniyle kazanabileceğimiz pratik değerleri henüz göremiyorum.

Nasıl WebClient(senkronizasyon çağrıları), HttpClient(senkronizasyon ve asenkron) performanslarını bulmak için hızlı bir performans testi yaptım . ve işte sonuçlar:

HttpClientTüm istekler için aynı örneği kullanma (min - maks)

WebClient senkronizasyonu: 8 ms - 167 ms
HttpClient senkronizasyonu: 3 ms - 7228 ms
HttpClient asenkronu: 985-10405 ms

HttpClientHer istek için yeni bir tane kullanma (min - maks)

WebClient senkronizasyonu: 4 ms - 297 ms
HttpClient senkronizasyonu: 3 ms - 7953 ms
HttpClient asenkronu: 1027 - 10834 ms

kod

public class AHNData
{
    public int i;
    public string str;
}

public class Program
{
    public static HttpClient httpClient = new HttpClient();
    private static readonly string _url = "http://localhost:9000/api/values/";

    public static void Main(string[] args)
    {
       #region "Trace"
       Trace.Listeners.Clear();

       TextWriterTraceListener twtl = new TextWriterTraceListener(
           "C:\\Temp\\REST_Test.txt");
       twtl.Name = "TextLogger";
       twtl.TraceOutputOptions = TraceOptions.ThreadId | TraceOptions.DateTime;

       ConsoleTraceListener ctl = new ConsoleTraceListener(false);
       ctl.TraceOutputOptions = TraceOptions.DateTime;

       Trace.Listeners.Add(twtl);
       Trace.Listeners.Add(ctl);
       Trace.AutoFlush = true;
       #endregion

       int batchSize = 1000;

       ParallelOptions parallelOptions = new ParallelOptions();
       parallelOptions.MaxDegreeOfParallelism = batchSize;

       ServicePointManager.DefaultConnectionLimit = 1000000;

       Parallel.For(0, batchSize, parallelOptions,
           j =>
           {
               Stopwatch sw1 = Stopwatch.StartNew();
               GetDataFromHttpClientAsync<List<AHNData>>(sw1);
           });
       Parallel.For(0, batchSize, parallelOptions,
            j =>
            {
                Stopwatch sw1 = Stopwatch.StartNew();
                GetDataFromHttpClientSync<List<AHNData>>(sw1);
            });
       Parallel.For(0, batchSize, parallelOptions,
            j =>
            {
                using (WebClient client = new WebClient())
                {
                   Stopwatch sw = Stopwatch.StartNew();
                   byte[] arr = client.DownloadData(_url);
                   sw.Stop();

                   Trace.WriteLine("WebClient Sync " + sw.ElapsedMilliseconds);
                }
           });

           Console.Read();
        }

        public static T GetDataFromWebClient<T>()
        {
            using (var webClient = new WebClient())
            {
                webClient.BaseAddress = _url;
                return JsonConvert.DeserializeObject<T>(
                    webClient.DownloadString(_url));
            }
        }

        public static void GetDataFromHttpClientSync<T>(Stopwatch sw)
        {
            HttpClient httpClient = new HttpClient();
            var response = httpClient.GetAsync(_url).Result;
            var obj = JsonConvert.DeserializeObject<T>(
                response.Content.ReadAsStringAsync().Result);
            sw.Stop();

            Trace.WriteLine("HttpClient Sync " + sw.ElapsedMilliseconds);
        }

        public static void GetDataFromHttpClientAsync<T>(Stopwatch sw)
        {
           HttpClient httpClient = new HttpClient();
           var response = httpClient.GetAsync(_url).ContinueWith(
              (a) => {
                 JsonConvert.DeserializeObject<T>(
                    a.Result.Content.ReadAsStringAsync().Result);
                 sw.Stop();
                 Trace.WriteLine("HttpClient Async " + sw.ElapsedMilliseconds);
              }, TaskContinuationOptions.None);
        }
    }
}

Sorularım

  1. REST çağrıları kabul edilebilir 3-4s içinde döner. Ajax çağrılarından çağrılan denetleyici yöntemlerinde REST hizmetine çağrılar başlatılır. Başlangıç ​​olarak, çağrılar farklı bir iş parçacığında çalışır ve kullanıcı arayüzünü engellemez. Peki, senkronizasyon çağrılarına sadık kalabilir miyim?
  2. Yukarıdaki kod yerel kutumda çalıştırıldı. Ürün kurulumunda DNS ve proxy araması yapılacaktır. HttpClientÜzerinden kullanmanın herhangi bir avantajı var mıWebClient ?
  3. HttpClientEşzamanlılık bundan daha mı iyi WebClient? Test sonuçlarından görüyorum WebClient senkronizasyon çağrılarının daha iyi performans gösterdiğini .
  4. Will HttpClientbiz .Net 4.5 yükseltme eğer daha iyi bir tasarım tercihi? Performans kilit tasarım faktörüdür.

5
GetDataFromHttpClientAsyncTestiniz haksızlıktır, çünkü önce çalışır, diğer çağrılar potansiyel olarak veri toplama (yerel makinede veya hedefinizle aranızdaki herhangi bir şeffaf proxy'de olsun) avantajından yararlanır ve daha hızlı olur. Ayrıca, doğru koşullar altında var response = httpClient.GetAsync("http://localhost:9000/api/values/").Result;vida dişi dişlerini yormanız nedeniyle bir kilitlenmeye neden olabilir. ThreadPool iş parçacıklarındaki iş parçacığı havuzuna bağlı bir etkinliği engellememelisiniz, awaitbunun yerine iş parçacığını havuza geri döndürür.
Scott Chamberlain

1
Web API İstemcisi ile HttpClient bir JSON / XML REST istemcisi için harika.
Cory Nelson

@Scott Chamberlain - Cevabınız için teşekkürler. Tüm test çağrıları Parallel.Foreach içinde çalıştığından, hangisinin önce çalışacağının garantisi yoktur. Ayrıca, hizmete ilk çağrı GetDataFromHttpClientAsync'den olsaydı, GetDataFromHttpClientAsync'ten sonraki tüm çağrıların önbellekten yararlanması ve daha hızlı çalışması gerekirdi. Bunu sonuçta görmedim. Rgd bekliyor, hala 4.0 kullanıyoruz. Senkronizasyon tarzında HttpClient'in kilitlenmeye yol açacağını kabul ediyorum ve bu seçeneği tasarım düşüncem dışında bırakıyorum.
user3092913

@CoryNelson HttpClient'in Web API İstemcisi ile neden bir JSON / XML REST istemcisi için harika olduğunu açıklayabilir misiniz?
user3092913

2
İşte HttpClient ve WebClient arasındaki farkla ilgili birkaç kelime: blogs.msdn.com/b/henrikn/archive/2012/02/11/…
JustAndrei

Yanıtlar:


243

Hem F # hem de Web API dünyalarında yaşıyorum.

Web API'sında, özellikle güvenlik için ileti işleyicileri vb. Şeklinde çok iyi şeyler oluyor.

Benimkinin sadece bir görüş olduğunu biliyorum, ancak gelecekteki herhangi bir iş için kullanılmasını tavsiye ederimHttpClient . Belki de System.Net.Httpbu montajı doğrudan kullanmadan çıkan diğer parçalardan bazılarını kullanmanın bir yolu var , ancak şu anda bunun nasıl çalışacağını hayal edemiyorum.

Bu ikisini karşılaştırmaktan bahsetmişken

  • HttpClient HTTP'ye WebClient'ten daha yakındır.
  • Rapor ilerlemesi, özel URI şeması ve WebClient'in sağladığı FTP çağrıları yapma gibi şeyler olduğundan, HttpClient'in Web İstemcisinin tamamen değiştirilmesi amaçlanmamıştır, ancak HttpClient bunu yapmaz.
+--------------------------------------------+--------------------------------------------+
|               WebClient                    |               HttpClient                   |
+--------------------------------------------+--------------------------------------------+
| Available in older versions of .NET        | .NET 4.5 only.  Created to support the     |
|                                            | growing need of the Web API REST calls     |
+--------------------------------------------+--------------------------------------------+
| WinRT applications cannot use WebClient    | HTTPClient can be used with WinRT          |
+--------------------------------------------+--------------------------------------------+
| Provides progress reporting for downloads  | No progress reporting for downloads        |
+--------------------------------------------+--------------------------------------------+
| Does not reuse resolved DNS,               | Can reuse resolved DNS, cookie             |
| configured cookies                         | configuration and other authentication     |
+--------------------------------------------+--------------------------------------------+
| You need to new up a WebClient to          | Single HttpClient can make concurrent      |
| make concurrent requests.                  | requests                                   |
+--------------------------------------------+--------------------------------------------+
| Thin layer over WebRequest and             | Thin layer of HttpWebRequest and           |
| WebResponse                                | HttpWebResponse                            |
+--------------------------------------------+--------------------------------------------+
| Mocking and testing WebClient is difficult | Mocking and testing HttpClient is easy     |
+--------------------------------------------+--------------------------------------------+
| Supports FTP                               | No support for FTP                         |
+--------------------------------------------+--------------------------------------------+
| Both Synchronous and Asynchronous methods  | All IO bound methods in                    |
| are available for IO bound requests        | HTTPClient are asynchronous                |
+--------------------------------------------+--------------------------------------------+

.NET 4.5 kullanıyorsanız, lütfen Microsoft'un geliştiricilere sağladığı HttpClient ile zaman uyumsuz iyiliği kullanın. HttpClient, HttpRequest ve HttpResponse olan HTTP sunucu tarafı kardeşleri için çok simetriktir.

Güncelleme: Yeni HttpClient API'sini kullanmak için 5 neden:

  • Güçlü yazı başlıkları.
  • Paylaşılan Önbellekler, çerezler ve kimlik bilgileri
  • Çerezlere ve paylaşılan çerezlere erişim
  • Önbellek ve paylaşılan önbellek üzerinde kontrol.
  • Kod modülünüzü ASP.NET kanalına enjekte edin. Daha temiz ve modüler kod.

Referans

C # 5.0 Joseph Albahari

(Kanal 9 - Video Derleme 2013)

Web Hizmetlerine Bağlanmak için Yeni HttpClient API'sini Kullanmanın Beş Büyük Nedeni

WebClient vs HttpClient vs HttpWebRequest


4
HttpClient'in .NET 4.0 için de kullanılabilir olduğu belirtilmelidir .
Todd Menier

2
Bu, WebClient'in neden HttpClient'ten daha hızlı olduğunu açıklamıyor. Ayrıca WebClientşimdi zaman uyumsuz yöntemler var gibi görünüyor.
ezmek

8
@crush, OP'nin her istek için yeni bir HttpClient örneği oluşturmasıdır. Bunun yerine uygulamanızın ömrü boyunca tek bir HttpClient örneği kullanmalısınız. Bkz. Stackoverflow.com/a/22561368/57369
Gabriel

6
Dikkat çeken WebClientmevcut değil .Net Coreama HttpClient.
Pranav Singh

3
Net Core 2.0 WebClient (diğer binlerce API arasında) geri döndüğünden ve kullanılabilir olduğundan.
CoderBang

56

HttpClient API'lerin daha yenisidir ve

  • iyi bir zaman uyumsuz programlama modeli var
  • temelde HTTP mucitlerinden Henrik F Nielson tarafından çalışıldı ve API'yi tasarladı, böylece HTTP standardını takip etmen kolay, örneğin standartlara uygun başlıkların oluşturulması
  • Net çerçevesi 4.5 içerisindedir, bu nedenle öngörülebilir gelecek için bazı garantili destek seviyesine sahiptir
  • .Net 4.0, Windows Phone vb. gibi diğer platformlarda kullanmak istiyorsanız kütüphanenin xcopyable / portable-framework sürümüne de sahiptir.

Diğer web hizmetlerine REST çağrıları yapan bir web hizmeti yazıyorsanız, tüm REST çağrılarınız için zaman uyumsuz bir programlama modeli kullanmak istersiniz, böylece iş parçacığı açlığına basmazsınız. Muhtemelen zaman uyumsuz / beklemede olan en yeni C # derleyicisini de kullanmak istersiniz.

Not: Daha performanslı bir AFAIK değildir. Adil bir test oluşturursanız muhtemelen benzer şekilde performans gösterir.


Proxy değiştirmek için bir yolu olsaydı deli olurdu
ed22

3

İlk olarak, özellikle WebClient vs. HttpClient üzerinde bir otorite değilim. İkincisi, yukarıdaki yorumlarınızdan, WebClient'in SADECE Senkronizasyon olduğunu, HttpClient'in ikisi de olduğunu öne sürüyor.

WebClient (Sync aramaları), HttpClient (Sync ve Async) 'in nasıl performans gösterdiğini bulmak için hızlı performans testi yaptım. ve işte sonuçlar.

Gelecek için düşünürken büyük bir fark olarak görüyorum, yani uzun süren süreçler, duyarlı GUI, vb.


4
WebClienten son .NET sürümlerinde zaman uyumsuzluk yeteneklerine sahip gibi görünüyor. Neden bu kadar büyük ölçekte HttpClient'ten daha iyi performans gösterdiğini bilmek istiyorum.
ezmek

1
Stackoverflow.com/a/4988325/1662973'e göre , birinin diğerinin soyutlaması olması dışında aynı gibi görünüyor. Belki, nesnelerin nasıl kullanıldığına / yüklendiğine bağlıdır. Minimum zaman, webclient'in aslında HttpClient'in bir soyutlaması olduğu ifadesini destekliyor, bu nedenle milisaniye değerinde bir ek yük var. Çerçeve, web istemcisinin gerçekten havuzlanması veya bertaraf edilmesi konusunda "sinsi" olabilir.
Anthony Horne


2

HttpClient, WebClient, HttpWebResponse arasında bir ölçüt var ve Rest Web Api'yi çağırıyorum

ve sonuç Çağrı Dinlenme Web Api Benchmark

--------------------- Aşama 1 ---- 10 Talep

{00: 00: 17.2232544} ====> HttpClinet

{00: 00: 04.3108986} ====> WebRequest

{00: 00: 04.5436889} ====> WebClient

--------------------- Aşama 1 ---- 10 Talep - Küçük Boy

{00: 00: 17,2232544} ====> HttpClinet

{00: 00: 04,3108986} ====> WebRequest

{00: 00: 04,5436889} ====> WebClient

--------------------- Aşama 3 ---- 10 senkronizasyon Talebi - Küçük Boy

{00: 00: 15,3047502} ====> HttpClinet

{00: 00: 03,5505249} ====> WebRequest

{00: 00: 04,0761359} ====> WebClient

--------------------- Aşama 4 ---- 100 senkronizasyon Talebi - Küçük Boy

{00: 03: 23,6268086} ====> HttpClinet

{00: 00: 47,1406632} ====> WebRequest

{00: 01: 01,2319499} ====> WebClient

--------------------- Aşama 5 ---- 10 senkronizasyon İsteği - Maks Boyut

{00: 00: 58,1804677} ====> HttpClinet

{00: 00: 58,0710444} ====> WebRequest

{00: 00: 38,4170938} ====> WebClient

--------------------- Aşama 6 ---- 10 senkronizasyon İsteği - Maks Boyut

{00: 01: 04,9964278} ====> HttpClinet

{00: 00: 59,1429764} ====> WebRequest

{00: 00: 32,0584836} ====> WebClient

_____ WebClient daha hızlı ()

var stopWatch = new Stopwatch();
        stopWatch.Start();
        for (var i = 0; i < 10; ++i)
        {
            CallGetHttpClient();
            CallPostHttpClient();
        }

        stopWatch.Stop();

        var httpClientValue = stopWatch.Elapsed;

        stopWatch = new Stopwatch();

        stopWatch.Start();
        for (var i = 0; i < 10; ++i)
        {
            CallGetWebRequest();
            CallPostWebRequest();
        }

        stopWatch.Stop();

        var webRequesttValue = stopWatch.Elapsed;


        stopWatch = new Stopwatch();

        stopWatch.Start();
        for (var i = 0; i < 10; ++i)
        {

            CallGetWebClient();
            CallPostWebClient();

        }

        stopWatch.Stop();

        var webClientValue = stopWatch.Elapsed;

// ------------------------- Fonksiyonlar

private void CallPostHttpClient()
    {
        var httpClient = new HttpClient();
        httpClient.BaseAddress = new Uri("https://localhost:44354/api/test/");
        var responseTask = httpClient.PostAsync("PostJson", null);
        responseTask.Wait();

        var result = responseTask.Result;
        var readTask = result.Content.ReadAsStringAsync().Result;

    }
    private void CallGetHttpClient()
    {
        var httpClient = new HttpClient();
        httpClient.BaseAddress = new Uri("https://localhost:44354/api/test/");
        var responseTask = httpClient.GetAsync("getjson");
        responseTask.Wait();

        var result = responseTask.Result;
        var readTask = result.Content.ReadAsStringAsync().Result;

    }
    private string CallGetWebRequest()
    {
        var request = (HttpWebRequest)WebRequest.Create("https://localhost:44354/api/test/getjson");

        request.Method = "GET";
        request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;

        var content = string.Empty;

        using (var response = (HttpWebResponse)request.GetResponse())
        {
            using (var stream = response.GetResponseStream())
            {
                using (var sr = new StreamReader(stream))
                {
                    content = sr.ReadToEnd();
                }
            }
        }

        return content;
    }
    private string CallPostWebRequest()
    {

        var apiUrl = "https://localhost:44354/api/test/PostJson";


        HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(new Uri(apiUrl));
        httpRequest.ContentType = "application/json";
        httpRequest.Method = "POST";
        httpRequest.ContentLength = 0;

        using (var httpResponse = (HttpWebResponse)httpRequest.GetResponse())
        {
            using (Stream stream = httpResponse.GetResponseStream())
            {
                var json = new StreamReader(stream).ReadToEnd();
                return json;
            }
        }

        return "";
    }

    private string CallGetWebClient()
    {
        string apiUrl = "https://localhost:44354/api/test/getjson";


        var client = new WebClient();

        client.Headers["Content-type"] = "application/json";

        client.Encoding = Encoding.UTF8;

        var json = client.DownloadString(apiUrl);


        return json;
    }

    private string CallPostWebClient()
    {
        string apiUrl = "https://localhost:44354/api/test/PostJson";


        var client = new WebClient();

        client.Headers["Content-type"] = "application/json";

        client.Encoding = Encoding.UTF8;

        var json = client.UploadString(apiUrl, "");


        return json;
    }

1
Yukarıdaki Gabriel'in yorumuna bakın. Kısacası, bir HttpClient örneği oluşturup yeniden kullanırsanız, HttpClient çok daha hızlıdır.
LT Dan

1

Belki de sorunu farklı bir şekilde düşünebilirsiniz. WebClientve HttpClientaslında aynı şeyin farklı uygulamalarıdır. Önerdiğim , Bağımlılık Enjeksiyon kalıbını uygulamanız boyunca bir IoC Kabı ile uygulamaktır. Düşük düzeyli HTTP aktarımından daha yüksek bir soyutlama düzeyine sahip bir istemci arabirimi oluşturmalısınız. Sen kullanmak beton sınıfları yazabilir hem WebClientveHttpClient ve ardından yapılandırma yoluyla uygulanmasını enjekte etmek IoC kapsayıcı kullanın.

Bu size arasında geçiş olacaktır yapmayı sağlayacak neler HttpClientveWebClient olan, üretim ortamında objektif olarak test yapabilmeniz için kolayca kolayca .

Yani aşağıdaki gibi sorular:

Net 4.5 sürümüne geçersek HttpClient daha iyi bir tasarım seçeneği olacak mı?

IoC kapsayıcısını kullanarak iki istemci uygulaması arasında geçiş yaparak nesnel olarak yanıtlanabilir. Burada, HttpClientveya hakkında herhangi bir ayrıntı içermeyen, bağımlı olabileceğiniz örnek bir arayüz bulunmaktadır WebClient.

/// <summary>
/// Dependency Injection abstraction for rest clients. 
/// </summary>
public interface IClient
{
    /// <summary>
    /// Adapter for serialization/deserialization of http body data
    /// </summary>
    ISerializationAdapter SerializationAdapter { get; }

    /// <summary>
    /// Sends a strongly typed request to the server and waits for a strongly typed response
    /// </summary>
    /// <typeparam name="TResponseBody">The expected type of the response body</typeparam>
    /// <typeparam name="TRequestBody">The type of the request body if specified</typeparam>
    /// <param name="request">The request that will be translated to a http request</param>
    /// <returns></returns>
    Task<Response<TResponseBody>> SendAsync<TResponseBody, TRequestBody>(Request<TRequestBody> request);

    /// <summary>
    /// Default headers to be sent with http requests
    /// </summary>
    IHeadersCollection DefaultRequestHeaders { get; }

    /// <summary>
    /// Default timeout for http requests
    /// </summary>
    TimeSpan Timeout { get; set; }

    /// <summary>
    /// Base Uri for the client. Any resources specified on requests will be relative to this.
    /// </summary>
    Uri BaseUri { get; set; }

    /// <summary>
    /// Name of the client
    /// </summary>
    string Name { get; }
}

public class Request<TRequestBody>
{
    #region Public Properties
    public IHeadersCollection Headers { get; }
    public Uri Resource { get; set; }
    public HttpRequestMethod HttpRequestMethod { get; set; }
    public TRequestBody Body { get; set; }
    public CancellationToken CancellationToken { get; set; }
    public string CustomHttpRequestMethod { get; set; }
    #endregion

    public Request(Uri resource,
        TRequestBody body,
        IHeadersCollection headers,
        HttpRequestMethod httpRequestMethod,
        IClient client,
        CancellationToken cancellationToken)
    {
        Body = body;
        Headers = headers;
        Resource = resource;
        HttpRequestMethod = httpRequestMethod;
        CancellationToken = cancellationToken;

        if (Headers == null) Headers = new RequestHeadersCollection();

        var defaultRequestHeaders = client?.DefaultRequestHeaders;
        if (defaultRequestHeaders == null) return;

        foreach (var kvp in defaultRequestHeaders)
        {
            Headers.Add(kvp);
        }
    }
}

public abstract class Response<TResponseBody> : Response
{
    #region Public Properties
    public virtual TResponseBody Body { get; }

    #endregion

    #region Constructors
    /// <summary>
    /// Only used for mocking or other inheritance
    /// </summary>
    protected Response() : base()
    {
    }

    protected Response(
    IHeadersCollection headersCollection,
    int statusCode,
    HttpRequestMethod httpRequestMethod,
    byte[] responseData,
    TResponseBody body,
    Uri requestUri
    ) : base(
        headersCollection,
        statusCode,
        httpRequestMethod,
        responseData,
        requestUri)
    {
        Body = body;
    }

    public static implicit operator TResponseBody(Response<TResponseBody> readResult)
    {
        return readResult.Body;
    }
    #endregion
}

public abstract class Response
{
    #region Fields
    private readonly byte[] _responseData;
    #endregion

    #region Public Properties
    public virtual int StatusCode { get; }
    public virtual IHeadersCollection Headers { get; }
    public virtual HttpRequestMethod HttpRequestMethod { get; }
    public abstract bool IsSuccess { get; }
    public virtual Uri RequestUri { get; }
    #endregion

    #region Constructor
    /// <summary>
    /// Only used for mocking or other inheritance
    /// </summary>
    protected Response()
    {
    }

    protected Response
    (
    IHeadersCollection headersCollection,
    int statusCode,
    HttpRequestMethod httpRequestMethod,
    byte[] responseData,
    Uri requestUri
    )
    {
        StatusCode = statusCode;
        Headers = headersCollection;
        HttpRequestMethod = httpRequestMethod;
        RequestUri = requestUri;
        _responseData = responseData;
    }
    #endregion

    #region Public Methods
    public virtual byte[] GetResponseData()
    {
        return _responseData;
    }
    #endregion
}

Tam kod

HttpClient Uygulaması

Uygulamasında eşzamansız olarak çalıştırmak Task.Runiçin kullanabilirsiniz WebClient.

Bağımlılık Enjeksiyonu, iyi yapıldığında düşük seviyeli kararlar almak zorunda kalma problemini hafifletmeye yardımcı olur. Sonuçta, gerçek cevabı bilmenin tek yolu hem canlı bir ortamda denemek hem de hangisinin en iyi sonucu verdiğini görmek. Bu oldukça mümkündür WebClientbazı müşteriler için iyi çalışabilir ve HttpClientdiğerleri için iyi çalışabilir. Bu yüzden soyutlama önemlidir. Bu, uygulamanın temel tasarımını değiştirmeden kodun hızlı bir şekilde değiştirilebileceği veya yapılandırmayla değiştirilebileceği anlamına gelir.


1

2020'den bu yana popüler olmayan görüş:

Öyle bir şey olursa ASP.NET için apps Hala tercih WebClientüzerinde HttpClientçünkü:

  1. Modern uygulama, zaman uyumsuz / beklenen görev tabanlı yöntemlerle birlikte gelir
  2. Daha az bellek alanı ve 2x-5x daha hızlıdır (diğer yanıtlar zaten bunu belirtmektedir)
  3. " Uygulamanızın ömrü boyunca tek bir HttpClient örneğini yeniden kullanmanız " önerilir . Ancak ASP.NET'in "uygulama ömrü" yoktur, yalnızca bir isteğin ömrü vardır.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.