ASP.NET WebApi を HttpClient の PostAsyncメソッドで呼び出し
- 評価
- クリップ 1
- VIEW 10K+
発生している問題・エラーメッセージ
以下が返されて、対象のPostメソッドは呼ばれません。The requested resource does not support http method 'GET'.
ソースコード
まず、WebApiの記述です。 [RoutePrefix("api/GateApi")]
public class GateApiController : ApiController
{
// パラメータ用のクラス定義
public class para
{
public int GateNo { get; set; }
}
// Post処理
[Route("TestPost")]
[HttpPost]
public string TestPost(para data)
{
return "Post呼ばれたよ";
}
}
試しに、同じサイト内のページに埋め込んだ、以下のJavascriptでPOSTしてみましたが、これは正常に処理されます。
値も正常に渡るし、戻り値も返っています。
function testPost() {
$.ajax(
"/api/GateApi/TestPost/",
{
type: "POST",
data: { GateNo: 333 },
success: function (data) {
alert(data);
},
error: function (e) {
alert("エラー");
}
});
}
以下が、Windows Formのソースの一部です。
ボタンをクリックするとレスポンスがラベルに表示されます。
private void button_Click(object sender, EventArgs e)
{
PostWebPageAsync();
}
private async void PostWebPageAsync()
{
this.label1.Text = "Post取得中";
string uri = "http://localhost:12345/api/GateApi/TestPost/";
// "Message":"The requested resource does not support http method 'GET'. が返されます。
this.label1.Text = await Post(uri,
new Dictionary<string, string> {{ "GateNo", "123" }});
}
// Post呼び出し処理
private async Task<string> Post(string url, Dictionary<string, string> param)
{
string result = "";
try
{
HttpClient httpClient = new HttpClient();
httpClient.MaxResponseContentBufferSize = int.MaxValue;
HttpContent content = new FormUrlEncodedContent(param);
var response = await httpClient.PostAsync(url, content);
String text = await response.Content.ReadAsStringAsync();
result = text;
}
catch (Exception Err)
{
result = "ERROR: " + Err.Message;
}
return result;
}
例外は発生していないようですが、ラベルには、
"Message":"The requested resource does not support http method 'GET'.
が表示されます。
response.StatusCode は MethodNotAllowed が返されます。
何か、ヘッダなど必要な情報があるんでしょうが、よくわかりません。
補足情報
サーバー側もクライアント側も、.NETのバージョンは 4.5.1IISのログの抜粋です
---------------------------------------------------------------------
■うまくいくとき → ChromeのRest Client で呼び出し
2015-10-13 03:06:50 ::1 POST /api/GateApi/TestPost - 12345 - ::1 Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/45.0.2454.101+Safari/537.36 - 200 0 0 2620
■うまくいかないとき → WindowsForm で呼び出し
2015-10-13 03:09:21 ::1 POST /api/GateApi/TestPost/ - 12345 - ::1 - - 302 0 0 13
2015-10-13 03:09:21 ::1 GET /api/GateApi/TestPost/ AspxAutoDetectCookieSupport=1 53903 - ::1 - - 405 0 0 266
---------------------------------------------------------------------
上記ログ(うまくいかないほう)とソースの対応を調べたのですが、
1行目: var response = await httpClient.PostAsync(url, content); → POST
2行目: String text = await response.Content.ReadAsStringAsync(); → GET
ということでした。
1行目の処理で、エラーが帰りそのため2行目のGETがうまくいかないということのようです。
1行目POST時の戻り値の内容を一部抜粋
---------------------------------------------------------------------
IsSuccessStatusCode: false
ReasonPhrase: "Method Not Allowed"
RequestMessage: {Method: POST, RequestUri: 'http://localhost:12345/api/GateApi/TestPost/?AspxAutoDetectCookieSupport=1', Version: 1.1, Content: System.Net.Http.FormUrlEncodedContent, Headers:
{
Content-Type: application/x-www-form-urlencoded
Content-Length: 10
}}
---------------------------------------------------------------------
[その後の調査]
eripong さん貴重な情報ありがとうございます。
セッションIDの受渡のために、クッキーを使うかどうかの設定の話だと思うんですが、私の知識では、いまいち細かいしくみがわかりません。ただ、これを機に多少とも勉強させていただきます。
最低限の私の知識で理解できる範囲で、以下いろいろやってみました。
■まず、cookieless の設定による実行結果です。(○がPOST成功)
× UseUri
○ UseCookies
× AutoDetect
○ UseDeviceProfile
おっしゃるように、UseCookiesだとうまくいくようで、UseDeviceProfileでも大丈夫みたいです。
つまり、設定としては、
- <sessionState mode="Off" />
- <sessionState cookieless="UseCookies"/>
- <sessionState cookieless="UseDeviceProfile"/>
■次に、Chromeのクッキーの状態を見てみました。

試しに、これを削除して、JavascriptやREST ClientツールでGETしてみると、見事にエラーになります。
ただ、このときに再度AspxAutoDetectCookieSupport=1 が保存され、2回目以降はエラーにならないようです。
■REST Client でのPOST実行結果
各処理のリクエストの内容を細かく調べる方法がわからないので、とりあえず情報として載せておきます。
以下は、REST Client でPOSTに失敗した時の状況です。

最後に、REST Client でPOSTに成功した時の状況です。

-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
rest - asp.net web api and aspxautodetectcookiesupport - Stack Overflow
では、セッションをoffにする事で現象が解消したとありますが、
セッションは使用されているでしょうか?offにすることはできますか?
問題が発生する仕組みについて
まず、POSTした後に、クエリストリングにAspxAutoDetectCookieSupport=1を付けてGETしているようなのは、sessionStateのcookielessがAutoDetectの場合に発生する様です。
今回の場合、最初のPOSTは、以下に述べるセッションのための処理を行うために、
ASP.NETによって処理され、二番目に来るGETを関数TestPostに振り分けようとして、
POSTにしか対応していないのでエラー、ということだと思います。
同じサイト内のページに埋め込んだJavascriptやChromeのRest Clientでうまくいったのは、
既に今回のアプリケーションにアクセスしており、リクエストにクッキーが載っていたためではないかと
予想しています。
(確認できれば、確認していただければと思います。)
セッションIDをクッキーに保存するかURLに埋め込むかを決めるために、
クッキーが使えるクライアントか、そうでないかを判定するために、
AspxAutoDetectCookieSupport=1にリダイレクトしています。
以下のページに詳しい判定方法が載っています。
Understand How the ASP.NET Cookieless Feature Works
また、SessionStateSection.Cookieless プロパティを見ると、
cookielessのデフォルトはAutoDetectの様なので、こちらをUseCookiesにすれば、
現象が解消する可能性はあります。
その場合、HttpClientでCookieが有効になる様にする必要があります。
ただ、UseCookiesにすればリダイレクトがなくなるかどうかについては、
今のところ有効な資料を見つけられておらず、また検証する環境もないので、
うまく行くかは未知数です。
UseUriは、セッションID付きのURLへのリダイレクトを伴うと思いますので、
いずれにしてもリダイレクトした場合にGETリクエストになって同じエラーになるかと思います。
(こちらも検証していないので予想です。)
セッション自体をなくしてしまえば、これらの仕組みが動かなくなるので、
セッションをoffにすれば改善するだろうと思って回答しました。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
ここに対策として,引数に[FromBody]属性を書く方法が載っています。javascriptの対処の方は以下の例ではクエリパラメータでリクエストを渡しているので今回は参考にしなくても大丈夫です。
以下の資料によれば,POSTメソッドの引数指定は文字列から変換できる型のみに限定されるようです。恐らく独自定義クラスだとキャストを定義する,インターフェースを継承する必要があるのではないかと思います。[FromBody]属性を付けるとリクエストを引数をbodyから受け取るようにして空のリクエストも引数有りにするのだと思います。(javascriptで正しく動いていることからURIに引数がないから怒られている可能性もあります。)
また,POSTリクエストをDictionary型で渡しているところも怪しいので文字列に変換してからリクエストしてみてはいかがでしょうか。
WebApi2 Requested resource does not support post
何が解決策になるか解りませんがいずれかの方法で解決するように思います。
追記:session offで解決するとのことなのでもしかすると,ASP.NETではリクエストヘッダかボディにデフォルトでセッションに使うパラメータが入っていて,それが引数の型で解釈できないせいでエラーが出ている可能性もあります。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.32%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
tkow
2015/10/11 16:12 編集
IISが使用しているポート番号が正しく設定されていますでしょうか?
IISはデフォルトでは通常の80や8080ポートではなく乱数であいているポートを使用していたと思うのでそうなっていないか確認してみてください。
skippanther
2015/10/13 08:51
とりあえずはVSのデバッグモードで実行しています。つまり、実行環境としてはデバッグ時に起動されるドメインとポート番号を指定しているということです。
ためしに、Chromeの拡張ツール Advanced Rest Clientで、ちゃんとこのメソッドが呼ばれることを確認しました。
skippanther
2015/10/13 09:25
ちなみに、ポートが間違っている場合は、
"ERROR: 無効な URI: 無効なポートが指定されています。"
が返されました。
eripong
2015/10/13 11:48
IISのログはどうなっていますか?POSTできているかや、うまく行く場合との差分の確認はできませんか?