Як правильно зробити http-веб-GET-запит


112

я все ще новачка на 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;
        }
    }
}

клас - це об'єкт, до нього звертаються з форми, просто розбираючи його ідентифікатор користувача та вносячи запит.

Я спробував багато прикладів, які я дивився на Google, але не розумію, чому я отримую на всі способи це повідомлення " ".

Я новачок у такому алгоритмі, якщо хтось може поділитися книгою чи підручником, де показано, як робити подібні речі (пояснюючи кожен крок), я би вдячний за це

Відповіді:


247

Іноді сервери стискають свої відповіді, щоб заощадити на пропускній здатності, коли це трапляється, вам потрібно видалити відповідь, перш ніж намагатися її прочитати. На щастя, .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();
    }
}

Отримати асинхронізацію

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

    

Async POST
Містить параметр 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, і це перший раз, коли я починаю розробляти програми для настільних ПК.
Оскар Рейєс

Привітання, ви можете поглянути на "Newtonsoft.Json", щоб десеріалізувати відповідь JSON, яку ви отримуєте.
Айдін

чи є шанс асинхронізувати версію
ahmad molaie

2
@ahmadmolaie Додав їх, а також як робити запити POST
Айдін

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
Дякую! Дуже корисно для мене. Я просто трохи змінив, додавши відповідь та вміст у операторі "using":
котрий

5
За aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong , ніколи не загортайте HttpClient у використовуваному операторі.
sfors повідомляє відновити Моніку

4
@sfors Ніколи не кажи ніколи. Подивіться на код. HttpClientПримірник використовується тільки один раз за життя програми і розташований безпосередньо перед виходом з програми. Це абсолютно правильно і доречно.
Тодд Меньє

Я не впевнений, як ви можете оспорити цю статтю та інші, як правильно створити екземпляр HttpClient. Використовуючи приватну статичну змінну, яку не можна розмістити. Через це, як цитується в цій статті: (щодо не використання розпорядження) ... "Але HttpClient інший. Хоча він реалізує інтерфейс IDisposable, він насправді є спільним об'єктом. Це означає, що під обкладинками є ретентом" і потоком Замість того, щоб створювати новий екземпляр HttpClient для кожного виконання, ви повинні поділитись одним екземпляром HttpClient протягом усього життя програми. "
sfors повідомляє відновити Моніку

Я розумію, що мій коментар запізнився на 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> імпліцитно введеній змінній!
Лука Циглер

Єдине оголошення null.i знаю that.i видалити null.
Manish sharma
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.