วิธีสร้างคำขอรับเว็บ http อย่างถูกต้อง


114

ฉันยังใหม่ใน c # และฉันกำลังพยายามสร้างแอปพลิเคชันสำหรับเพจนี้ซึ่งจะแจ้งให้ฉันทราบเมื่อฉันได้รับการแจ้งเตือน (ตอบแสดงความคิดเห็น ฯลฯ ... ) แต่ตอนนี้ฉันแค่พยายามโทรไปที่ api ง่ายๆซึ่งจะได้รับข้อมูลของผู้ใช้

ฉันใช้ Visual studio express 2012 เพื่อสร้างแอปพลิเคชัน C # โดยที่ (ตอนนี้) คุณป้อนรหัสผู้ใช้ของคุณดังนั้นแอปพลิเคชันจะส่งคำขอด้วยรหัสผู้ใช้และแสดงสถิติของรหัสผู้ใช้นี้

นี่คือรหัสที่ฉันพยายามส่งคำขอ:

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

คลาสเป็นอ็อบเจ็กต์และถูกเข้าถึงจากฟอร์มโดยเพียงแค่แยกวิเคราะห์ id ผู้ใช้และทำการร้องขอ

ฉันได้ลองดูหลายตัวอย่างใน Google แล้ว แต่ไม่ทราบสาเหตุว่าทำไมฉันถึงได้รับข้อความ " " นี้ทุกวิธี

ฉันเป็นคนใหม่ในอัลกอริทึมประเภทนี้หากใครสามารถแบ่งปันหนังสือหรือบทช่วยสอนที่แสดงวิธีการทำสิ่งนี้ (อธิบายแต่ละขั้นตอน) ฉันจะขอบคุณ

คำตอบ:


250

บางครั้งเซิร์ฟเวอร์จะบีบอัดการตอบสนองเพื่อประหยัดแบนด์วิดท์เมื่อเกิดเหตุการณ์นี้คุณต้องคลายการตอบสนองก่อนที่จะพยายามอ่าน โชคดีที่. NET framework สามารถทำได้โดยอัตโนมัติอย่างไรก็ตามเราต้องเปิดการตั้งค่า

นี่คือตัวอย่างของวิธีที่คุณจะบรรลุเป้าหมายนั้น

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

รับ

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

รับ async

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
มีพารามิเตอร์methodในกรณีที่คุณต้องการใช้วิธี HTTP อื่น ๆ เช่น 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
มีพารามิเตอร์methodในกรณีที่คุณต้องการใช้วิธี HTTP อื่น ๆ เช่น 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();
    }
}

4
fyi คุณอาจต้องการแสดงตัวอย่างวิธีการแยกวิเคราะห์htmlสตริง+1เพื่อทำความสะอาดโค้ดโดยวิธี ..
MethodMan

ขอบคุณฉันไม่รู้เกี่ยวกับการคลายการบีบอัดฉันเป็นนักพัฒนา php / nodejs และนี่เป็นครั้งแรกที่ฉันเริ่มพัฒนาแอปเดสก์ท็อป
Oscar Reyes

ยินดีต้อนรับคุณคุณอาจต้องการดูที่ 'Newtonsoft.Json' เพื่อยกเลิกการกำหนดค่าการตอบสนอง JSON ที่คุณดึงมา
Aydin

มีโอกาสที่จะ async เวอร์ชันใดบ้าง
ahmad molaie

2
@ahmadmolaie เพิ่มพวกเขารวมถึงวิธีการทำคำขอ POST
Aydin

39

อีกวิธีหนึ่งคือการใช้ 'HttpClient' เช่นนี้:

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 กับ HttpWebRequest

อัปเดต 22 มิถุนายน 2020: ไม่แนะนำให้ใช้ httpclient ในบล็อก 'โดยใช้' เนื่องจากอาจทำให้พอร์ตหมดได้

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+ ให้พิจารณาใช้IHttpClientFactoryและฉีดสิ่งนี้ในรหัสเริ่มต้นของคุณ

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

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

1
ขอบคุณ! มีประโยชน์มากสำหรับฉัน ฉันเพิ่งแก้ไขเล็กน้อยโดยใส่คำตอบและเนื้อหาในคำสั่ง "ใช้":
รหัส


4
@sfors ไม่เคยพูดไม่เคย ดูรหัส HttpClientเช่นถูกนำมาใช้ครั้งเดียวสำหรับชีวิตของโปรแกรมและทิ้งก่อนที่จะออกจากโปรแกรม ที่ถูกต้องและเหมาะสมอย่างสมบูรณ์
Todd Menier

ฉันไม่แน่ใจว่าคุณจะโต้แย้งบทความนั้นและคนอื่น ๆ เกี่ยวกับการสร้างอินสแตนซ์ของ HttpClient ได้อย่างไร ใช้ตัวแปรคงที่ส่วนตัวซึ่งไม่ได้รับการกำจัด ด้วยเหตุนี้ดังที่ยกมาในบทความนั้น: (เกี่ยวกับการไม่ใช้การกำจัด) ... "แต่ HttpClient แตกต่างออกไปแม้ว่าจะใช้อินเทอร์เฟซ IDisposable แต่ก็เป็นวัตถุที่ใช้ร่วมกันซึ่งหมายความว่าภายใต้ฝาครอบจะมีการ reentrant) และเธรด ปลอดภัยแทนที่จะสร้างอินสแตนซ์ใหม่ของ HttpClient สำหรับการดำเนินการแต่ละครั้งคุณควรแชร์ HttpClient เพียงอินสแตนซ์เดียวตลอดอายุการใช้งานของแอปพลิเคชัน "
sfors กล่าวว่าคืนสถานะ Monica ใน

ฉันตระหนักดีว่าความคิดเห็นของฉันช้าไป 2 ปี แต่ทอดด์ไม่ได้โต้แย้งบทความนี้ ทอดด์พูดง่ายๆว่าจากตัวอย่างโปรแกรมแบบเต็ม HttpClient เดียวจะใช้ตลอดอายุการใช้งานของแอปพลิเคชัน
จอห์น

4

วิธีที่ง่ายที่สุดสำหรับความคิดเห็นของฉัน

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

หรือ

 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
รหัสไม่ทิ้งวัตถุ อาจเป็นการรั่วไหลของหน่วยความจำ ต้องใช้งบ.
StarTrekRedneck

คุณไม่สามารถกำหนด <null> ให้กับตัวแปรที่พิมพ์โดยนัยได้!
Luca Ziegler

มันเพียงประกาศ null ฉันรู้ว่าฉันลบ null
Manish sharma
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.