🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

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

ASP.NET Web API

ASP.NET Web APIはブラウザやモバイル機器のようなクライアント向けのHTTPサービスを構築するフレームワークです。Microsoft .NET Frameworkがベースになっており、RESTfulサービスを構築するには理想的です。

Q&A

解決済

1回答

4466閲覧

HttpClientクラスを使ったjsonデータのPOSTについて

ws12

総合スコア1

C#

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

ASP.NET Web API

ASP.NET Web APIはブラウザやモバイル機器のようなクライアント向けのHTTPサービスを構築するフレームワークです。Microsoft .NET Frameworkがベースになっており、RESTfulサービスを構築するには理想的です。

0グッド

0クリップ

投稿2020/12/11 07:12

編集2020/12/11 09:09

お世話になっております。
C#のHttpClientクラスを使ってPOSTする場合、WebAPI側(ASP.NET WebAPI .NetFramework4.7.2)で受けるPOSTメソッドの引数の書き方によってはメソッドにアクセスできない(404エラー)になります。

HttpClientを使ったクライアント側サンプル(.Net Core コンソールアプリケーションにて)

C#

1var client = new HttpClient(); 2var content = new StringContent(json, Encoding.UTF8, "application/json"); 3var response = await client.PostAsync("http://localhost/api/person", content);

アクセス可能なPOSTメソッド(クラスで受け取る)

C#

1public HttpResponseMessage PostPerson(Person person) 2{}

アクセス不可能なPOSTメソッド(プリミティブな型で受け取る)

C#

1public HttpResponseMessage PostPerson(string id, string name) 2{}

補足

POSTMANを使った場合は上記どちらのケースでもアクセス可能で、むしろ下記のようにサーバー側を記述してもアクセス可能です

C#

1public HttpResponseMessage PostPerson(Person person, string id, string name) 2{ 3 // personにもid, nameにも値が入る 4}

HttpClientを使ったjsonデータのPOSTで、プリミティブな型で受ける方法はありますでしょうか?

追記

WebAPI及びクライアント側のフレームワーク情報を追記しました。
HttpClientの使用方法はusingを使わないように修正しました。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2020/12/11 08:38

.NET Framework なのか Core なのかとそのバージョンを書いてください。
退会済みユーザー

退会済みユーザー

2020/12/11 08:45

> (404エラー)になります。 404 に間違いないですか? 404 というのは要求はサーバーに届いたが指定された url にリソースが見つからないということなのですが・・・ あと、本題とは関係ないことですが質問のコードのように using 句を使って HttpClient の初期化と Dispose を繰り返すと socket の枯渇につながりますので止めましょう。
ws12

2020/12/11 09:05

ご指摘ありがとうございます。 > 404 に間違いないですか? 404 NotFoundで間違いありません。 > .NET Framework なのか Core 今回はどちらか関係なさそう(HttpClient側の問題?)と推測しておりましたので省略しておりました。追記しておきます。 > using 句を使って HttpClient HttpClientはインスタンスを使い回す、といったところですね。サンプルのため特に考慮せず、ネットで拾ったものを流用しておりました。こちらも念のため修正しておきますね。
guest

回答1

0

ベストアンサー

.NET Framework 版の ASP.NET Web API のバインディングについては、詳しくは以下の記事、それからリンクを張った MSDN Blog の記事「How WebAPI does Parameter Binding」に書いてありますのでそちらを読んでもらうとして、要点を書きますと・・・

(1) Model Binding または Formatters を利用するという 2 つの方法があって、Web API の場合は、クエリ文字列からパラメータを取得する場合は Model Binding を、ボディから取得する場合は Formatter を使う。

(2) string などのプリミティブ型をアクションメソッドの引数にした場合、引数に属性が付与されてなければクエリ文字列からパラメータを探してモデルバインディングする。

(3) コンプレックス型(例:下に紹介した記事のコードの Hero クラス)の場合、デフォルトでは Formatter を使ってボディからパラメータを取得する。

さらに、MSDN Blog の記事に "The body can only be read once" と書いてある点にも要注意です。

ASP.NET Web API のバインディング
http://surferonwww.info/BlogEngine/post/2018/09/11/aspnet-web-api-parameter-binding.aspx

なので、「アクセス不可能なPOSTメソッド(プリミティブな型で受け取る)」の以下のようなメソッドで id と name にボディから値を得ることはできないということになります。

public HttpResponseMessage PostPerson(string id, string name) {}

POSTMANを使った場合は上記どちらのケースでもアクセス可能で

それは何かの勘違いではないですか? クライアント側は関係ないはずです。Fiddler などのキャプチャツールを使って調べてください。

投稿2020/12/11 10:12

編集2020/12/11 10:24
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

ws12

2020/12/11 11:46

ご回答ありがとうございます。 初歩的なミスをしており、POSTMANで送信していたものは、jsonデータ以外にクエリパラメータが付与されておりました。このクエリパラメータに反応していたようで、こちらを削除したところ、POSTMANでも404エラーとなり、プリミティブな型での受け取りはできませんでした。 そもそもASP.NET WebAPIで、bodyの値をそのようなパラメータで受けることはできないのですね。 またjsonでpostされたデータを[frombody]を付与したプリミティブな型で受けることもできないのですね。jsonでPOSTするなら素直にクラス定義して受けます。 記載いただいたWebサイトも大変参考になりました、ありがとうございました。 また合わせて下記MSのページも参考にしましたので、備忘録として記載させていただきます。 https://docs.microsoft.com/ja-jp/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問