HTTP Web GETリクエストを適切に行う方法


112

私はまだc#の新人であり、通知(応答、コメントなど)を受け取ったときに通知するこのページのアプリケーションを作成しようとしています。しかし、今のところ、ユーザーのデータを取得するapiを単純に呼び出そうとしています。

私はVisual Studio Express 2012を使用してC#アプリケーションを構築しています。ここでは、ユーザーIDを入力するため、アプリケーションはユーザーIDを使用してリクエストを作成し、このユーザーIDの統計を表示します。

これが私がリクエストを作成しようとしているコードです:

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を解析してリクエストを行うだけで、フォームからアクセスされます。

私はグーグルで見た例の多くを試しましたが、なぜこのメッセージ「 」をすべての方法で受け取っているのかわかりません。

私はこの種のアルゴリズムの新人です。誰かがこの種のことをする方法を示す本やチュートリアルを共有できれば(各ステップを説明します)、それを感謝します

回答:


247

サーバーは時々応答を圧縮して帯域幅を節約します。これが発生した場合、応答を読み取ろうとする前に圧縮解除する必要があります。幸い、.NETフレームワークはこれを自動的に実行できますが、設定をオンにする必要があります。

これを実現する方法の例を次に示します。

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には、PUT、DELETE、ETCなどの他のHTTPメソッドを使用する場合の
パラメーター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などの他のHTTPメソッドを使用する場合のイベント
のパラメーター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
FYIあなたは、解析する方法の例を示したいことがありhtml、文字列+1の方法によりクリーンなコードのために...
メソッド・マン

ありがとう、解凍について知らなかった。私はphp / nodejs開発者であり、これがデスクトップアプリでの開発を始めるのはこれが初めてである。
オスカーレイエス

ようこそ、 'Newtonsoft.Json'を見て、取得したJSON応答をデシリアライズしてください。
アイディン2014年

バージョンを非同期にする可能性はありますか
ahmad molaie 2017年

2
@ahmadmolaieがそれらを追加し、POSTリクエストを実行する方法を追加
Aydin

38

別の方法は、次のように「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

2020年6月22日更新: ポートを使い果たす可能性があるため、「using」ブロックで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」ステートメントで囲むことにより、少しだけ変更しました:
codely

5
aspnetmonsters.com/2016/08/2016-08-27-httpclientwrongごとに、HttpClientをusingステートメントでラップしないでください。
sforsはモニカを2017

4
@sfors決して言うことはありません。コードを見てください。HttpClientインスタンスは、プログラムの生活のために一度だけ使用され、単にプログラムが終了する前に配置されています。それは完全に正しく、適切です。
トッドメニア2017

HttpClientのインスタンスを適切に作成する方法について、その記事や他の記事にどのように異議を唱えることができるかわかりません。破棄されないプライベート静的変数を使用する。このため、その記事で引用されているように:(disposeを使用しないことに関して)...「しかし、HttpClientは異なります。これはIDisposableインターフェイスを実装していますが、実際には共有オブジェクトです。つまり、内部では再入可能です)およびスレッド安全。実行ごとにHttpClientの新しいインスタンスを作成する代わりに、アプリケーションの存続期間全体にわたってHttpClientの単一のインスタンスを共有する必要があります。」
sforsはモニカを2017

私のコメントは2年では遅すぎることに気づきましたが、Toddは記事に異議を唱えていませんでした。Toddは、完全なプログラムの例を考えると、アプリケーションの存続期間中に単一のHttpClientが使用されると単純に言っていました。
John

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 2016年

暗黙的に型指定された変数に<null>を割り当てることはできません!
Luca Ziegler

その唯一のnullを宣言します。iはnullを削除します。
Manish sharma
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.