Cara membuat permintaan GET web http dengan benar

112

saya masih baru di c # dan saya mencoba membuat aplikasi untuk halaman ini yang akan memberi tahu saya ketika saya mendapat pemberitahuan (dijawab, dikomentari, dll ..). Tetapi untuk saat ini saya hanya mencoba membuat panggilan sederhana ke api yang akan mendapatkan data pengguna.

Saya menggunakan Visual studio express 2012 untuk membangun aplikasi C #, di mana (untuk saat ini) Anda memasukkan id pengguna Anda, sehingga aplikasi akan membuat permintaan dengan id pengguna dan menampilkan statistik dari id pengguna ini.

berikut adalah kode tempat saya mencoba membuat permintaan:

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

kelas adalah sebuah objek dan sedang diakses dari formulir dengan hanya mem-parsing id pengguna dan membuat permintaan.

Saya telah mencoba banyak contoh yang saya lihat di google, tetapi tidak tahu mengapa saya mendapatkan semua cara pesan ini " ".

Saya baru dalam algoritme semacam ini, jika ada yang dapat berbagi buku atau tutorial yang menunjukkan cara melakukan hal semacam ini (menjelaskan setiap langkah), saya akan sangat menghargainya

Oscar Reyes
sumber

Jawaban:

247

Server terkadang memampatkan responsnya untuk menghemat bandwidth, jika ini terjadi, Anda perlu mendekompresi respons sebelum mencoba membacanya. Untungnya, kerangka .NET dapat melakukan ini secara otomatis, namun, kita harus mengaktifkan pengaturannya.

Inilah contoh bagaimana Anda bisa mencapainya.

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

DAPATKAN

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

DAPATKAN asinkron

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
Berisi parameter methodjika Anda ingin menggunakan metode HTTP lain seperti PUT, DELETE, ETC

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
Berisi parameter methodjika Anda ingin menggunakan metode HTTP lain seperti PUT, DELETE, ETC

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();
    }
}
Aydin
sumber
4
html+1
Perlu diketahui,
terima kasih, saya tidak tahu tentang dekompresi, saya adalah pengembang php / nodejs dan ini adalah pertama kalinya saya mulai mengembangkan aplikasi desktop.
Oscar Reyes
Selamat datang, Anda mungkin ingin melihat 'Newtonsoft.Json' untuk menghentikan respons JSON yang Anda ambil.
Aydin
apakah ada kemungkinan untuk versi asinkron
ahmad molaie
2
@ahmadmolaie Menambahkannya, serta cara melakukan permintaan POST
Aydin
39

Cara lain adalah menggunakan 'HttpClient' seperti ini:

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

Pembaruan 22 Juni 2020: Tidak disarankan menggunakan httpclient dalam blok 'menggunakan' karena dapat menyebabkan kehabisan port.

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

Jika menggunakan .Net Core 2.1+, pertimbangkan untuk menggunakan IHttpClientFactory dan menyuntikkan seperti ini ke kode startup Anda.

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

 services.AddHttpClient<XApiClient>().ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
        {
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
        }).AddPolicyHandler(request => timeout);
MENGGALI
sumber
1
Terima kasih! Sangat berguna bagi saya. Saya baru saja memodifikasi sedikit dengan melampirkan tanggapan dan konten dalam pernyataan "menggunakan":
codely
5
Menurut aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong , jangan pernah membungkus HttpClient dalam pernyataan menggunakan.
sfors mengatakan memulihkan Monica
4
@pengen Lihat kodenya. The HttpClientcontoh digunakan tepat sekali untuk kehidupan program dan dibuang sebelum keluar program. Itu sepenuhnya benar dan tepat.
Todd Menier
Saya tidak yakin bagaimana Anda dapat menyengketakan artikel itu dan artikel lainnya tentang cara membuat instance HttpClient dengan benar. Menggunakan variabel statis pribadi, yang tidak dibuang. Karena itu, seperti yang dikutip dalam artikel itu: (mengenai tidak menggunakan buang) ... "Tetapi HttpClient berbeda. Meskipun mengimplementasikan antarmuka IDisposable, ini sebenarnya adalah objek bersama. Artinya, di balik sampul itu adalah reentrant) dan utas aman. Daripada membuat instance baru HttpClient untuk setiap eksekusi, Anda harus membagikan satu instance HttpClient untuk seluruh masa pakai aplikasi. "
sfors mengatakan memulihkan Monica
Saya menyadari komentar saya terlambat 2 tahun, tetapi Todd tidak membantah artikel tersebut. Todd hanya mengatakan bahwa dengan contoh program lengkap, satu HttpClient digunakan untuk kehidupan aplikasi.
Yohanes
4

Cara paling sederhana menurut saya

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

ATAU

 var bytes = web.DownloadData(url);
Сергей Кислинский
sumber
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();
    }
}
Manish sharma
sumber
5
kode tidak membuang objek; bisa jadi kebocoran memori. Kebutuhan menggunakan pernyataan.
StarTrekRedneck
Anda tidak dapat menetapkan <null> ke variabel yang diketik secara implisit!
Luca Ziegler
Ini hanya mendeklarasikan null. Saya tahu itu. Saya menghapus null.
Manish sharma