Bir http web GET isteği nasıl düzgün bir şekilde yapılır?


113

Hala c # üzerinde yeniyim ve bu sayfa için bir bildirim aldığımda (yanıtlandı, yorum yapıldı, vb.) bana haber verecek bir uygulama oluşturmaya çalışıyorum. Ama şimdilik, kullanıcının verilerini alacak olan api'ye basit bir çağrı yapmaya çalışıyorum.

(şimdilik) kullanıcı kimliğinizi girdiğiniz C # uygulamasını oluşturmak için Visual studio express 2012 kullanıyorum, böylece uygulama, kullanıcı kimliğiyle istekte bulunacak ve bu kullanıcı kimliğinin istatistiklerini gösterecektir.

İşte istekte bulunmaya çalıştığım kod:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Request library
using System.Net;
using System.IO;

namespace TestApplication
{
    class Connect
    {
        public string id;
        public string type;

        protected string api = "https://api.stackexchange.com/2.2/";
        protected string options = "?order=desc&sort=name&site=stackoverflow";

        public string request()
        {
            string totalUrl = this.join(id);

            return this.HttpGet(totalUrl);
        }

        protected string join(string s)
        {
            return api + type + "/" + s + options;
        }

        protected string get(string url)
        {
            try
            {
                string rt;

                WebRequest request = WebRequest.Create(url);

                WebResponse response = request.GetResponse();

                Stream dataStream = response.GetResponseStream();

                StreamReader reader = new StreamReader(dataStream);

                rt = reader.ReadToEnd();

                Console.WriteLine(rt);

                reader.Close();
                response.Close();

                return rt;
            }

            catch(Exception ex)
            {
                return "Error: " + ex.Message;
            }
        }
        public string HttpGet(string URI)
        {
            WebClient client = new WebClient();

            // Add a user agent header in case the 
            // requested URI contains a query.

            client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");

            Stream data = client.OpenRead(URI);
            StreamReader reader = new StreamReader(data);
            string s = reader.ReadToEnd();
            data.Close();
            reader.Close();

            return s;
        }
    }
}

sınıf bir nesnedir ve formdan sadece kullanıcı kimliğini ayrıştırarak ve istekte bulunarak erişilir.

google'da baktığım örneklerin çoğunu denedim, ancak bu " " mesajını neden tüm yollardan aldığımı bilmiyorum.

Bu tür bir algoritmada yeniyim, eğer herhangi biri bu tür şeylerin nasıl yapılacağını gösteren bir kitap veya öğretici paylaşabilirse (her adımı açıklayarak) çok sevinirim

Yanıtlar:


249

Sunucular bazen bant genişliğinden tasarruf etmek için yanıtlarını sıkıştırır, bu olduğunda, okumaya çalışmadan önce yanıtın sıkıştırmasını açmanız gerekir. Neyse ki, .NET çerçevesi bunu otomatik olarak yapabilir, ancak ayarı açmamız gerekiyor.

İşte bunu nasıl başarabileceğinize dair bir örnek.

string html = string.Empty;
string url = @"https://api.stackexchange.com/2.2/answers?order=desc&sort=activity&site=stackoverflow";

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.AutomaticDecompression = DecompressionMethods.GZip;

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
    html = reader.ReadToEnd();
}

Console.WriteLine(html);

ALMAK

public string Get(string uri)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

    using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    using(Stream stream = response.GetResponseStream())
    using(StreamReader reader = new StreamReader(stream))
    {
        return reader.ReadToEnd();
    }
}

Eşzamansız GET

public async Task<string> GetAsync(string uri)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

    using(HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync())
    using(Stream stream = response.GetResponseStream())
    using(StreamReader reader = new StreamReader(stream))
    {
        return await reader.ReadToEndAsync();
    }
}

POST PUT, DELETE, ETC gibi diğer HTTP yöntemlerini kullanmak istemeniz durumunda
parametreyi içerir.method

public string Post(string uri, string data, string contentType, string method = "POST")
{
    byte[] dataBytes = Encoding.UTF8.GetBytes(data);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
    request.ContentLength = dataBytes.Length;
    request.ContentType = contentType;
    request.Method = method;

    using(Stream requestBody = request.GetRequestStream())
    {
        requestBody.Write(dataBytes, 0, dataBytes.Length);
    }

    using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    using(Stream stream = response.GetResponseStream())
    using(StreamReader reader = new StreamReader(stream))
    {
        return reader.ReadToEnd();
    }
}

    

POST async PUT, DELETE, ETC gibi diğer HTTP yöntemlerini kullanmak istemeniz durumunda
parametreyi içerir.method

public async Task<string> PostAsync(string uri, string data, string contentType, string method = "POST")
{
    byte[] dataBytes = Encoding.UTF8.GetBytes(data);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
    request.ContentLength = dataBytes.Length;
    request.ContentType = contentType;
    request.Method = method;

    using(Stream requestBody = request.GetRequestStream())
    {
        await requestBody.WriteAsync(dataBytes, 0, dataBytes.Length);
    }

    using(HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync())
    using(Stream stream = response.GetResponseStream())
    using(StreamReader reader = new StreamReader(stream))
    {
        return await reader.ReadToEndAsync();
    }
}

4
Bu arada temiz kod için htmldizeyi nasıl ayrıştıracağınıza dair bir örnek göstermek isteyebilirsiniz +1..
MethodMan

teşekkür ederim, sıkıştırmanın açılmasını bilmiyordum, ben bir php / nodejs geliştiricisiyim ve masaüstü uygulamalarında geliştirmeye ilk kez başladım.
Oscar Reyes

Hoş geldiniz, aldığınız JSON yanıtını seri durumdan çıkarmak için 'Newtonsoft.Json'a bir göz atmak isteyebilirsiniz.
Aydın

eşzamansız sürüm için herhangi bir şans var mı
ahmad molaie

2
@ahmadmolaie Bunları ve ayrıca POST isteklerini nasıl yapacağını ekledi
Aydın

39

Başka bir yol da 'HttpClient' kullanmaktır:

using System;
using System.Net;
using System.Net.Http;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Making API Call...");
            using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }))
            {
                client.BaseAddress = new Uri("https://api.stackexchange.com/2.2/");
                HttpResponseMessage response = client.GetAsync("answers?order=desc&sort=activity&site=stackoverflow").Result;
                response.EnsureSuccessStatusCode();
                string result = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine("Result: " + result);
            }
            Console.ReadLine();
        }
    }
}

HttpClient vs HttpWebRequest

22 Haziran 2020 Güncellemesi: Bağlantı noktasının tükenmesine neden olabileceğinden httpclient'i 'kullanma' bloğunda kullanmanız önerilmez.

private static HttpClient client = null;
    
ContructorMethod()
{
   if(client == null)
   {
        HttpClientHandler handler = new HttpClientHandler()
        {
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
        };        
        client = new HttpClient(handler);
   }
   client.BaseAddress = new Uri("https://api.stackexchange.com/2.2/");
   HttpResponseMessage response = client.GetAsync("answers?order=desc&sort=activity&site=stackoverflow").Result;
   response.EnsureSuccessStatusCode();
   string result = response.Content.ReadAsStringAsync().Result;
            Console.WriteLine("Result: " + result);           
 }

.Net Core 2.1+ kullanıyorsanız, IHttpClientFactory kullanmayı ve başlangıç ​​kodunuza bu şekilde enjekte etmeyi düşünün .

 var timeout = Policy.TimeoutAsync<HttpResponseMessage>(
            TimeSpan.FromSeconds(60));

 services.AddHttpClient<XApiClient>().ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
        {
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
        }).AddPolicyHandler(request => timeout);

1
Teşekkür ederim! Benim için çok faydalı. Yanıtı ve içeriği "using" ifadesinin içine
ekleyerek

5
Aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong başına , HttpClient'i hiçbir zaman bir using deyimi içine sarmayın.
sfors, Monica'yı

4
@sfors Asla asla deme. Koda bak. HttpClientÖrnek programın ömrü için tam bir kez kullanılır ve sadece programı çıkmadan önce yerleştirilir. Bu tamamen doğru ve uygundur.
Todd Menier

Bu makaleye ve diğerlerine HttpClient örneğinin düzgün bir şekilde nasıl oluşturulacağı konusunda nasıl itiraz edebileceğinizden emin değilim. İmha edilmeyen özel bir statik değişken kullanmak. Bu nedenle, bu makalede alıntılandığı gibi: (dispose kullanmama ile ilgili olarak) ... "Ama HttpClient farklıdır. IDisposable arayüzü uygulamasına rağmen aslında paylaşılan bir nesnedir. Bu, kapakların altında reentrant olduğu anlamına gelir) ve thread güvenli. Her yürütme için yeni bir HttpClient örneği oluşturmak yerine, uygulamanın tüm ömrü boyunca tek bir HttpClient örneğini paylaşmalısınız. "
sfors, Monica'yı

Yorumumun 2 yıl geç olduğunun farkındayım, ancak Todd makaleye itiraz etmiyordu. Todd, tam program örneği verildiğinde, uygulamanın ömrü boyunca tek bir HttpClient'in kullanıldığını söylüyordu.
John

4

Benim fikrim için en basit yol

  var web = new WebClient();
  var url = $"{hostname}/LoadDataSync?systemID={systemId}";
  var responseString = web.DownloadString(url);

VEYA

 var bytes = web.DownloadData(url);

3
var request = (HttpWebRequest)WebRequest.Create("sendrequesturl");
var response = (HttpWebResponse)request.GetResponse();
string responseString;
using (var stream = response.GetResponseStream())
{
    using (var reader = new StreamReader(stream))
    {
        responseString = reader.ReadToEnd();
    }
}

5
kod nesneleri atmaz; bellek sızıntısı olabilir. İfadelerin kullanılması gerekiyor.
StarTrekRedneck

Örtük olarak yazılmış bir değişkene <boş> atayamazsınız!
Luca Ziegler

Onun tek bildirimi null.i bunu biliyorum. İ kaldır null.
Manish sharma
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.