質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

Q&A

解決済

3回答

24715閲覧

C#でリクエストヘッダーとボディを一緒に送信する

Chandler_Bing

総合スコア673

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

0グッド

0クリップ

投稿2019/10/28 00:22

編集2019/10/29 00:11

実現したいことは以下のサイトのブロードキャストメッセージを送るの部分です。
Messaging APIリファレンス

他サイトを参考に以下のようなコードを作成しました。

C#

1 // To creat HttpClient 2 var client = new HttpClient(); 3 4 // Accesstoken 5 var accessToken = "token"; 6 7 // URL 8 var url = "https://api.line.me/v2/bot/message/multicast"; 9 10 // Message 11 var json = "{ \"type\" : text, \"text\" : \"Hello World\" }"; 12 // var content = new StringContent("{ \"your\": \"content\", \"maybe\": \"json\" }"); 13 // content.Headers.Add("X-SOME-RANDOM", "header-value"); 14 15 var request = new HttpRequestMessage(HttpMethod.Get, url); 16 // Request Header 17 request.Headers.Add("ContentType", "application/json"); 18 request.Headers.Add("Authorization", "Bearer " + accessToken); 19 // Request Body 20 request.Headers.Add("to", "userId"); 21 request.Headers.Add("messages", json); 22 var response = await client.SendAsync(request);

これを実行するとインターナルサーバーエラーになります。
リクエストヘッダーを設定する箇所は以下のサイトを参考にしました。
HttpClient でリクエストヘッダを設定する

リクエストヘッダーをそのまま、リクエストボディに適用した形です。
これだとよろしくないのでしょうか。

追記⓵
リクエストヘッダーとボディを分けるところは完成しましたが、どのようにして
ヘッダーにAuthorizationを設定すればよいでしょうか。現在のコードは以下です。

C#

1 var json = @"{""type"":""text"", ""text"":Hello World}"; 2 var content = new StringContent(json, Encoding.UTF8, @"application/json"); 3 4 using (var client = new HttpClient()) 5 { 6 var response = await client.PostAsync($"http://foo.example.com", content); 7 }

追記⓶
現在のコードは以下です。ボディとヘッダーを同時に設定できました。

C#

1 // To creat HttpClient 2 var client = new HttpClient(); 3 4 // Accesstoken 5 var accessToken = "token"; 6 7 // URL 8 var url = "https://api.line.me/v2/bot/message/broadcast"; 9 10 11 var request = new HttpRequestMessage(HttpMethod.Post, url); 12 // Request Header 13 request.Headers.Add("Authorization", "Bearer " + accessToken); 14 var parameters = new Dictionary<string, string>() 15 { 16 { "messages", "Hello World" }, 17 }; 18 19 request.Content = new StringContent( 20 parameters.ToString(), 21 Encoding.UTF8, 22 "application/json" 23 ); 24 25 await client.SendAsync(request);//ここでデバックで停止

デバック結果
イメージ説明

値も指定通りになっている気がします。
特にサーバーエラー等は出ていません。

追記⓷
現在、ローカルホストを外部に公開するためにngrokを使用しています。そこでは200Okのレスポンスが返ってきます。
が、fiddlerではエラーになっているようです。
以下がその画面と、現在のコードです。
イメージ説明

// To creat HttpClient var client = new HttpClient(); // Accesstoken var accessToken = "token="; // URL var url = "https://api.line.me/v2/bot/message/broadcast"; // POST var request = new HttpRequestMessage(HttpMethod.Post, url); // Request Header request.Headers.Add("Authorization", "Bearer " + accessToken); var str1 = new Dictionary<string, string>(); str1.Add("type", "text"); str1.Add("text", "test test test"); var str2 = new Dictionary<string, Dictionary<string, string>>(); str2.Add("messages", str1); var json = JsonConvert.SerializeObject(str2); request.Content = new StringContent( json.ToString(), Encoding.UTF8, "application/json" ); await client.SendAsync(request);

追記④
現在POSTでブロードキャストメッセージを送ると以下のようにFiddlerに表示されます。

POST https://api.line.me/v2/bot/message/broadcast HTTP/1.1 Authorization: Bearer my token Content-Type: application/json; charset=utf-8 Host: api.line.me Content-Length: 52 Expect: 100-continue Connection: Keep-Alive {"messages":{"type":"text","text":"test test test"}}

レスポンスは400(Bad request)になっています。
見た感じだと、APIリファレンスの要求に沿っている気がするのですが、どこかおかしいい箇所がありますでしょうか。

ちなにみに以下が現在成功している、マルチメッセージのFiddlerの結果です。比べても大きな違いはない気がします。
また、マルチメッセージはテンプレートの既存メソッドを指定しています。

POST https://api.line.me/v2/bot/message/multicast HTTP/1.1 Authorization: Bearer my token Content-Type: application/json; charset=utf-8 Host: api.line.me Content-Length: 143 Expect: 100-continue Connection: Keep-Alive {"to":["ID1","ID2"],"messages":[{"type":"text","text":"マルチメッセージ"}]}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2019/10/28 00:36

GetとPostの違いは分かってますよね。PHPでもJavaでも出てきているものですけど
m.ts10806

2019/10/28 00:38

あと参考先はあくまで参考であって自分がやりたいことを実現してくれるものでないということも当然理解していますよね
m.ts10806

2019/10/28 01:16

「もう少し、調べます」 調べてください。自分で書いてて人に調べさせることを「調べる」と表現しているのですか?作業依頼なら然るべきところに依頼し、きちんと報酬を支払ってください。 何度も言ってますがあなたの作業を代わりにやってくれる場所ではありません。規約違反として通報しておきましょうか?
m.ts10806

2019/10/28 02:09

またアクセストークン出しっぱなしですけど、前に複数のユーザーから重々指摘を喰らったはずです。忘れていいことではないですよ。さいあく、乗っ取られても悪用されてもそれにより社会的に制裁食らってもいいってことですかね。
m.ts10806

2019/10/28 02:14

これも何度も注意してますが、編集したところで編集履歴から確認できるんですよ。ウッカリで済まされることじゃないって認識持ってください。被害を被るのはあなただけでは済まないのです。 その程度の意識しかないならプログラミングから手を引いてください。
m.ts10806

2019/10/28 02:18

回答がつくと削除依頼が直接できないからすぐに非表示にもならない。運営確認が必要だから問い合わせが必要になり時間もかかる。 慎重に慎重を重ねないといけない場面で「あとで編集すればいっか」程度の認識しかないのは致命的です。 最近それで活動自粛した有名な芸人さんがいますが、同じことです。 ルーズな人にはプログラミングは全く不向きどころか周囲に大損害を与えるだけだ
guest

回答3

0

リクエストヘッダーをそのまま、リクエストボディに適用した形です。

これだとよろしくないのでしょうか。

はい、このままだと、To: userIdのようなHTTPヘッダを指定する意味になってしまいます。

リクエストボディは、HttpRequestMessage.Contentプロパティから指定してください(MSDN)。

あと、当該APIはPOSTなのに、HttpMethod.GetGETリクエストを作成しているようです。

投稿2019/10/28 00:29

maisumakun

総合スコア145934

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Chandler_Bing

2019/10/28 00:59

ありがとうございます。 もう少し、調べます。
Chandler_Bing

2019/10/28 01:40

以下のようなメッソドが使用できるようですね。 CopyToAsync(Stream) CopyToAsync(Stream, TransportContext) CreateContentReadStreamAsync() Dispose() Dispose(Boolean) Equals(Object) GetHashCode() GetType() LoadIntoBufferAsync() LoadIntoBufferAsync(Int64) MemberwiseClone() ReadAsByteArrayAsync() ReadAsStreamAsync() ReadAsStringAsync() SerializeToStreamAsync(Stream, TransportContext) ToString() TryComputeLength(Int64) しかし、ネットでボディを調べると、 var json = @"{""foo"":""hoge"", ""bar"":123, ""baz"":[""あ"", ""い"", ""う""]}"; using (var client = new HttpClient()) { var response = await client.PostAsync($"http://foo.example.com", content); ... } のような感じで指定しているのですが、これをどのように組み合わせればよいかイマイチわかりません。
maisumakun

2019/10/28 01:46

> ネットでボディを調べると、(中略)のような感じで指定しているのですが えっと、「HTTPContent+PostAsync」と「HttpRequestMessage+SendAsync」と、どちらの方法でやりたいのですか?使う関数が違えばやりかたも違ってきます。「ネットで調べたから」といって簡単に方法を変えてしまうと、何もかも書き直しになってしまいます。
Chandler_Bing

2019/10/28 01:55

申し訳ございません。さらなる調査により、コードを変更し、デバックも行ったので、状況を追記します。
Chandler_Bing

2019/10/28 02:09

HttpRequestMessage+SendAsyncで実現したいなと現段階では考えております。
guest

0

ユーザー認証用のトークンが取得できているのか疑問ですが、そこは本題とは関係ないようなのでとりあえず置いといて・・・

追記⓶
現在のコードは以下です。ボディとヘッダーを同時に設定できました。

そのコードでとりあえず送信はできているようですが、リクエストボディが API の要求に合ってないように思えます。(トークンの話は上に書いたようにちょっと置いといて)

参考にされている「Messaging APIリファレンス」を見ると、リクエストボディとして messages プロパティにメッセージオブジェクトの配列を設定して JSON 文字列で送信するということのようです。

そのリクエストボディが StringContent の第一引数の parameters.ToString() ということになりますが、実際どうなっているかデバッガを使うなどして調べてみてください。

あと、API とのやり取りを見るには Fiddler を使うのがお勧めです。以下の画像はベアラトークンを要求する API に JSON 文字列を POST 送信したときの要求・応答をキャプチャした結果です。

イメージ説明

トークンを含めたヘッダ情報が正しく設定され、リクエストボディとして JSON 文字列が期待通り設定されているかどうかが確認できます。また、応答も HTTP 200 と正常であることも確認できます。

投稿2019/10/28 04:07

編集2019/10/28 04:16
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Chandler_Bing

2019/10/28 05:17

回答ありがとうございます。 確認⓵ '{ "messages":[ { "type":"text", "text":"Hello, world1" }, { "type":"text", "text":"Hello, world2" } ] }' をJSON文字列で記述して、送信ということでしょうか。 確認⓶ また、Content-typeの設定は request.Headers.Add("Authorization", "Bearer " + accessToken); のようにAdd()で行うべき(String Contentでは行わない)でしょうか???
退会済みユーザー

退会済みユーザー

2019/10/28 05:30

> 確認⓵ それを聞くならマルチポスト https://teratail.com/questions/219750 を何とかしてください。 > 確認⓶ 今のコードで上の回答の Fiddler 画像の Content-type の通りとなるはずです。そういうことを確認するために Fiddler を使うことをお勧めしているのですから、聞く前にやってみましょう。
Chandler_Bing

2019/10/28 07:01

ありがとうございます。ダウンロードしました。 が、そもそも送信するJSON文字列が間違っていおりました。 現在はそこで落ちてしまいます。
m.ts10806

2019/10/28 09:34 編集

マルチポストよりアクセストークンの問題を。(何度目だろうこれ) →あぁそういうこと・・・運営依頼したか何かなら返事してほしいですね。無視されてる気しかしない。
guest

0

自己解決

お疲れ様です。お騒がせしました。
解決いたしました。

流れとしては以下のようになりました。

POSTしたいJSON値をオブジェクト化する→シリアライズ→ToStirngで文字列

オブジェクト化に関しては、以下のサイトを参考にしました。
http://json2csharp.com/

ヘッダーとボディの設定に関しては、質問本文にあるリンク先と以下のサイトを参考にしました。
https://codeday.me/jp/qa/20190601/916764.html

SurferOnWww様に教えていただいたFiddlerも非常に助けとなりました。
ありがとうございました。

投稿2019/10/29 01:32

Chandler_Bing

総合スコア673

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問