酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

HttpWebRequestを使ってPOSTメソッドでリクエストしてみた (Reactive Extensions編)

イラスト(写真)系SNSの「TINAMI」にはWebAPIが提供されています。認証を行わなくても新着イラストの一覧を取得することは可能ですが、年齢制限やpublic公開していないイラストを取得するためには認証が完了している必要があります。

認証処理はPOSTメソッドを投げる必要があります。.NETでPOSTメソッドのリクエストを行おうとするとリクエストストリームにデータを書き込んで、更にレスポンスストリームを取得する必要があります。

Windows Phoneは、基本非同期メソッドをする必要があるので、Rxを使って実装してみました。

public void PostRequest(string url, Dictionary<string, string> dic) {

  // クエリ文字列の生成
  var postData = string.Join("&",
      dic.Select(p => string.Format("{0}={1}", p.Key, p.Value)).ToArray()
  );

  var req = HttpWebRequest.CreateHttp(url);
  req.AllowAutoRedirect = false;
  req.Method = "POST";
  req.ContentType = "application/x-www-form-urlencoded";

  var writeStreamObservable = 
      Observable.FromAsyncPattern<Stream>(req.BeginGetRequestStream, req.EndGetRequestStream);
  var responseObservable = 
      Observable.FromAsyncPattern<WebResponse>(req.BeginGetResponse, req.EndGetResponse);

  writeStreamObservable()
      .SelectMany(reqStrm => {
          var buf = Encoding.UTF8.GetBytes(postData);
          reqStrm.Write(buf, 0, buf.Length);
          reqStrm.Close();
          return responseObservable();
      })
      .Select(res => {
          using (var s = new StreamReader(res.GetResponseStream()))
              return s.ReadToEnd();
      })
      .ObserveOnDispatcher()
      .Subscribe(text => textBlock1.Text = text);
}

使い方としてこんな感じ。ボタンをタップした時に、POSTリクエストを行うのを想定しています。

private void button2_Click(object sender, RoutedEventArgs e) {
  var dic = new Dictionary<string, string>() {
          { "api_key", "アプリキー" },
          { "email", "hoge@example.com" }, 
          { "password", "パスワード" }
  };
  PostRequest("http://api.tinami.com/auth", dic);
}

こんな感じになったんだけど結構微妙な気がする。

大人しくneuecc先生のWebRequest拡張メソッド(neue cc - Reactive Extensions用のWebRequest拡張メソッド)を使わせてもらった方が良いかもしれないですね……