Cách thực hiện đúng yêu cầu GET trên web http


112

tôi vẫn là người mới trên c # và tôi đang cố gắng tạo một ứng dụng cho trang này. Ứng dụng này sẽ cho tôi biết khi tôi nhận được thông báo (đã trả lời, nhận xét, v.v.). Nhưng hiện tại tôi chỉ đang cố thực hiện một cuộc gọi đơn giản tới api sẽ lấy dữ liệu của người dùng.

tôi đang sử dụng Visual studio express 2012 để tạo ứng dụng C #, trong đó (hiện tại) bạn nhập id người dùng của mình, vì vậy ứng dụng sẽ thực hiện yêu cầu với id người dùng và hiển thị số liệu thống kê của id người dùng này.

đây là mã mà tôi đang cố gắng thực hiện yêu cầu:

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

lớp là một đối tượng và nó được truy cập từ biểu mẫu bằng cách phân tích cú pháp id người dùng và thực hiện yêu cầu.

Tôi đã thử nhiều ví dụ mà tôi đã xem trên google, nhưng không biết tại sao tôi lại nhận được thông báo này bằng mọi cách " ".

tôi là người mới trong loại thuật toán này, nếu ai đó có thể chia sẻ một cuốn sách hoặc hướng dẫn chỉ ra cách thực hiện loại công cụ này (giải thích từng bước), tôi sẽ đánh giá cao nó

Câu trả lời:


247

Máy chủ đôi khi nén phản hồi của chúng để tiết kiệm băng thông, khi điều này xảy ra, bạn cần giải nén phản hồi trước khi cố gắng đọc nó. May mắn thay, .NET framework có thể thực hiện điều này tự động, tuy nhiên, chúng ta phải bật cài đặt này.

Đây là một ví dụ về cách bạn có thể đạt được điều đó.

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

ĐƯỢC

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

NHẬN 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
Chứa tham số methodtrong trường hợp bạn muốn sử dụng các phương thức HTTP khác như 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
Chứa tham số methodtrong trường hợp bạn muốn sử dụng các phương thức HTTP khác như 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 bạn có thể muốn hiển thị một ví dụ về cách phân tích cú pháp htmlchuỗi +1cho mã sạch bằng cách này ..
MethodMan

cảm ơn bạn, tôi không biết về giải nén, tôi là nhà phát triển php / nodejs và đây là lần đầu tiên tôi bắt đầu phát triển ứng dụng trên máy tính để bàn.
Oscar Reyes

Chào mừng bạn, bạn có thể muốn xem 'Newtonsoft.Json' để giải mã phản hồi JSON mà bạn truy xuất.
Aydin

là có bất kỳ cơ hội để phiên bản async
ahmad molaie

2
@ahmadmolaie Đã thêm chúng, cũng như cách thực hiện yêu cầu ĐĂNG
Aydin

38

Một cách khác là sử dụng 'HttpClient' như thế này:

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 so với HttpWebRequest

Cập nhật ngày 22 tháng 6 năm 2020: Không nên sử dụng httpclient trong khối 'đang sử dụng' vì nó có thể gây cạn kiệt cổng.

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

Nếu sử dụng .Net Core 2.1+, hãy cân nhắc sử dụng IHttpClientFactory và chèn như thế này vào mã khởi động của bạn.

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

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

1
Cảm ơn bạn! Rất hữu ích cho tôi. Tôi chỉ sửa đổi một chút bằng cách đính kèm câu trả lời và nội dung trong câu lệnh "using":
codely

5
Theo aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong , không bao giờ bọc HttpClient trong một câu lệnh using.
sfors nói Khôi phục Monica

4
@sfors Đừng bao giờ nói không bao giờ. Nhìn vào mã. Phiên bản HttpClientđược sử dụng chính xác một lần cho vòng đời của chương trình và được xử lý ngay trước khi chương trình thoát. Điều đó là hoàn toàn chính xác và phù hợp.
Todd Menier

Tôi không chắc làm thế nào bạn có thể tranh chấp bài viết đó và những người khác về cách tạo một bản sao HttpClient đúng cách. Sử dụng một biến tĩnh riêng tư, không bị loại bỏ. Bởi vì điều này, như được trích dẫn trong bài báo đó: (liên quan đến việc không sử dụng vứt bỏ) ... "Nhưng HttpClient thì khác. Mặc dù nó triển khai giao diện IDisposable nhưng nó thực sự là một đối tượng được chia sẻ. Điều này có nghĩa là dưới các trang bìa, nó là reentrant) và chuỗi an toàn. Thay vì tạo một phiên bản mới của HttpClient cho mỗi lần thực thi, bạn nên chia sẻ một phiên bản HttpClient trong toàn bộ thời gian của ứng dụng. "
sfors nói Khôi phục Monica

Tôi nhận ra nhận xét của mình đã quá muộn 2 năm, nhưng Todd đã không phản đối bài báo. Todd chỉ đơn giản nói rằng với ví dụ chương trình đầy đủ, một HttpClient duy nhất được sử dụng cho vòng đời của ứng dụng.
John

4

Cách đơn giản nhất cho ý kiến ​​của tôi

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

HOẶC LÀ

 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
mã không loại bỏ các đối tượng; có thể là một rò rỉ bộ nhớ. Cần sử dụng các câu lệnh.
StarTrekRedneck

Bạn không thể gán <null> cho một biến được định kiểu ngầm!
Luca Ziegler

Khai báo duy nhất của nó là null. Tôi biết điều đó. Tôi loại bỏ null.
Manish sharma,
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.