Windows Store App
HTTP通信を振り返る
楽しいアプリ制作の会(たのアプ)
大場知悟
@tworks
0
1
自己紹介
• 大場知悟(Tomonori Ohba)@tworks
本名を強いられているッ!
2
自己紹介
• コミュニティー
新大阪アプリ開発初級~中級者向け勉強会
楽しいアプリ制作の会 主催
http://tanoapp.tworks.jp/
• Windowsストアアプリ、iOS、Androidアプリ
を開発する闘うアラフォープログラマ
(※体力的に)
3
アプリケーション
通信を行うアプリケーション
使っていますか?
何がありますか?
4
アプリケーション
さて今日は
Windows 8 Store App
についてしゃべります
5
Windows Store アプリ
Windows 8は
タブレットを前提としたUI
≒モバイルユース前提
=通信はほぼ必須
6
通信するアプリがないとき~
7
通信するアプリがあるとき~!
8
通信するアプリがないとき~(再)
9
通信するアプリがあるとき~!!(再)
10
アプリケーション
通信を行うアプリケーション
あれば楽しいですよね。
※個人的な感想です
11
アプリケーション
通信を行うアプリケーション
通信中にProgressとか動かしたり
TLを表示したりすると
何かやってる感がある!
※個人的なry
12
何かやっていると思わせることは大事
13
なので…
半ば必須となっている
通信処理
を
一緒につくりましょう!
14
HTTPは手軽で便利
• データを取得するならHTTPで十分
– テキストデータ、バイナリデータ
• データ(not File)の送信もHTTPでOK
• 世の中、HTTPのサービスが大多数
– ○○APIとか全部HTTPですね
15
しかしHTTP上でやることは色々ある
• Cookieを付ける
– アカウント認証状態とか
• リクエストヘッダーを付ける(UA)
– 必要に応じて
• Basic認証/Digest認証
• 通信タイムアウト
16
通信するだけじゃ終われない
• HTTPはデータ(文字列)を取るところまで
• 文字列=JSONやXMLなどの文書
• JSONやXMLをアプリケーションで使える
形にしないとツラい
17
JSON
この配列にアクセスしたいです…
{
"groupName": "Cod2013 Room2",
"persons": [
{ "name": "Tomonori Ohba", "age": 39 },
{ "name": "Chuki Manabe", "age": 45 },
{ "name": "Taro Yamada", "age": 31 },
{ "name": "Hoge Fuga", "age": 21 }
]
}
18
XML
ここの、ここの、このノードが欲しい…
<root>
<groupName>CoD2013 Room2</groupName>
<persons>
<person>
<name>Tomonori Ohba</name>
<age>39</age>
</person>
<person>
<name>Chuki Manabe</name>
<age>45</age>
19
アジェンダ
• HTTP通信のユースケースをおさえよう
– 単純なGET/POST
– Cookieを付ける
– リダイレクトのハンドリング
– バイナリデータの取得
– BackgroundDownloader
• 取得したデータを使いやすくしよう
– JSON/XML Parse
20
(1)単純なGET/POST
DEMO
21
(1)単純なGET
using (var handler = new HttpClientHandler())
using (var httpClient = new HttpClient(handler))
{
var httpResponseMessage =
await httpClient.GetAsync(uri);
var content =
await httpResponseMessage.Content.ReadAsStringAsync();
}
22
(1)単純なPOST
using (var handler = new HttpClientHandler())
using (var httpClient = new HttpClient(handler))
using (var formUrlEncodedContent = new
FormUrlEncodedContent(queryParams)) // Dictionary<string,string>
{
var httpResponseMessage =
await httpClient.PostAsync(uri, formUrlEncodedContent);
var content =
await httpResponseMessage.Content.ReadAsStringAsync();
}
23
(1)単純なGET/POST
3つのクラス(GETは2つ)で構成される
• HttpClientHandler
HTTPの通信前後で 処理をフック するもの(後述)
• HttpClient
HTTP通信の本体
• FormUrlEncodedContent
POSTパラメタを構成するもの
24
(2)Cookie
DEMO
25
(2)Cookieを付ける
var handler = HttpClientHandler();
// 単一のCookieを生成
var cookie = new Cookie("Key", "Value");
// CookieContainerにCookieをセット
var container = new CookieContainer();
container.Add(new Uri("somedomain.com"), cookie);
// HttpClientHandlerへCookieをセット
handler.CookieContainer = container;
26
(3)リダイレクトのハンドリング
DEMO
27
(3)リダイレクトのハンドリング
using (var handler = new HttpClientHandler())
using (var httpClient = new HttpClient(handler))
{
handler.AllowAutoRedirect = false;
var res = await httpClient.GetAsync(uri);
if (res == HttpStatusCode.Redirect)
{
// res.Headers.Location がリダイレクト先URL
}
28
(4)バイナリデータの取得
DEMO
29
(4)バイナリデータの取得
var stream = await
httpResponseMessage.Content.ReadAsStreamAsync();
var binaryReader = new BinaryReader(stream);
var contentBytes = new byte[contentLength]
binaryReader.Read(contentBytes, 0, contentBytes.Length);
30
(TIPS)DelegatingHandler
DEMO
31
DelegatingHandler
HttpClient
GetAsync()
CustomHandler
override SendAsync()
32
(5)WinRTにダウンロードを委譲
BackgroundDownloader
DEMO
33
(5)BackgroundDownloader
var destinationFile = await
KnownFolders.DocumentsLibrary.CreateFileAsync("save.bin"), Crea
tionCollisionOption.ReplaceExisting);
var downloader = new BackgroundDownloader();
var download = downloader.CreateDownload(new
Uri(@"http://somedomain/test/hoge.bin"), destinationFile);
await download.StartAsync();
34
BackgroundDownloader
• ダウンロード中にアプリを中断・終了す
るとダウンロードも中断します
• アプリケーション再開時に、前回中断し
たダウンロードを再開する方法もありま
す
Windows 8 アプリ開発者ブログ
http://blogs.msdn.com/b/windowsappdev_ja/archive/2012/05/21/being-
productive.aspx
35
取得したデータのオブジェクト化
DEMO
36
JSON
{
"groupName": "Cod2013 Room2",
"persons": [
{ "name": "Tomonori Ohba", "age": 39 },
{ "name": "Chuki Manabe", "age": 45 },
{ "name": "Taro Yamada", "age": 31 },
{ "name": "Hoge Fuga", "age": 21 }
]
}
37
JSON Parse 受けるPropの作成
[DataContract]
public class PersonJson
{
[DataMember(Name="name")]
public string Name { get; set; }
[DataMember(Name = "age")]
public int Age { get; set; }
}
38
JSON Parse 受けるPropの作成
[DataContract]
public class PersonsJson
{
[DataMember(Name="groupName")]
public string GroupName { get; set; }
[DataMember(Name="persons")]
public List<PersonJson> Persons { get; set; }
}
39
JSONのParseとインスタンス化
var dataContractJsonSerializer = new
DataContractJsonSerializer(typeof(PersonJson));
var memoryStream = new
MemoryStream(Encoding.Unicode.GetBytes(json));
var personJsonInstalce =
(PersonJson)dataContractJsonSerializer.ReadObject(memoryStream
);
40
GeneicにしちゃえばOK
public static T ToClass<T>(string json) {
var dataContractJsonSerializer = new
DataContractJsonSerializer(typeof(T));
var memoryStream = new
MemoryStream(Encoding.Unicode.GetBytes(json)))
return
(T)dataContractJsonSerializer.ReadObject(memoryStream);
}
41
JSONの要素アクセス
// LINQでよろしく
var me = (
from person in json.Persons
where person.Name == "Tomonori Ohba"
select person
).FirstOrDefault();
42
XML Parse
var xdoc = XDocument.Parse(xml);
43
XMLのNodeアクセス
// LINQでよろしく
var me = (
from person in xdoc.Descendants("person")
where person.Element("name").Value == "Tomonori Ohba“
select person
).FirstOrDefault();
44
取得したデータの加工
• JSONはDataContractでオブジェクト化が可能
変換後のクラスをあらかじめ用意するのが面倒
(インテリセンスが効くメリットがあります)
• シリアライズ時に、DataMemberで指定したNameが、
JSONオブジェクト名に紐づけられます
• XMLはXdocumntでシリアライズ、Node探索はゴリ系
45
まとめ
46
まとめ
• テキストデータを取得するなら
HttpClient#GetAsync/PostAsyncで
• HTTPの上に乗るProtocolを実装するときは
DetegatingHandler
• 取ってきてファイルに出すなら
BackgroundDownloader
• JSON/XMLは良しなにParse~Linqで料理
47
素敵なアプリを作りましょう!
48
ご清聴ありがとうございまし
た。

Windows Store App HTTP通信を振り返る