どのようにPOST動詞を使用してページにリダイレクトしますか?


131

RedirectToActionコントローラ内で呼び出すと、HTTP GETを使用して自動的にリダイレクトされます。HTTP POSTを使用するように明示的に指示するにはどうすればよいですか?

GETリクエストとPOSTリクエストの両方を受け入れるアクションがあり、POSTをRedirectToAction使用していくつかの値を送信できるようにしたいと考えています。

このような:

this.RedirectToAction(
    "actionname",
    new RouteValueDictionary(new { someValue = 2, anotherValue = "text" })
);

someValueとのanotherValue値を、GETではなくHTTP POSTを使用して送信したい。誰でもこれを行う方法を知っていますか?


jasonによる回答投稿はほとんどのシナリオで機能しますが、私が目にする唯一の問題は、事故が起こりやすいことです。つまり、アクションメソッドを呼び出すと、アクションに適用されているすべてのフィルターが直接バイパスされます。そのため、アクションメソッドに適用された認証またはカウンターの種類のフィルターがある場合、そのデータは失われる可能性があります。アクションメソッドを直接呼び出すことは機能しますが、慎重に適用する必要があります。
amarnathチャタジー

回答:


103

HTTPは、POSTを使用したページへのリダイレクトをサポートしていません。どこかにリダイレクトすると、HTTPの "Location"ヘッダーがブラウザーに移動先を通知し、ブラウザーはそのページに対してGET要求を行います。おそらく、GET要求とPOST要求を受け入れるために、ページのコードを記述する必要があります。


4
なぜ私の答えが受け入れられないのか興味があるので、私のレトリックは健全だと思います。:)もう一度、私はそれについて少し偏見があるかもしれません...
Jason Bunting 2010年

14
この答えは基本的に正しいですが、完全ではありません。より優れた回避策については、以下のJason Buntingの回答を参照してください。
エイドリアン

160

あなたの特定の例については、私はこれを行います、あなたが明らかにブラウザに実際にとにかくリダイレ​​クトを取得させることにあなたが気にしていないからです(あなたがすでに受け入れた答えを受け入れることによって):

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index() {
   // obviously these values might come from somewhere non-trivial
   return Index(2, "text");
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(int someValue, string anotherValue) {
   // would probably do something non-trivial here with the param values
   return View();
}

それは簡単に機能し、実際に起こっている面白いビジネスはありません-これにより、2つ目は本当にHTTP POSTリクエストのみを受け入れるという事実を維持できます(この場合は、とにかく制御下にあります)。 TempDataを使用します。これは、回答に投稿したリンクが示唆しているものです。

何かあったら、これで何が「間違っている」のか知りたいです。明らかに、本当にブラウザーにリダイレクトを送信したいのであれば、これは機能しませんが、私には奇妙に思えるため、なぜそれを変換しようとするのかを尋ねるべきです。

お役に立てば幸いです。


7
あなたが反対票を投じられた理由を誰が知っていますか。これは非常に便利な方法です。
Peter J

2
これは私がいつもこの問題を解決する方法でもあります。これに反対票を投じても意味がありません。
エイドリアン・グリゴール、2011年

39
私は賛成票を投じましたが、知らない人に馬鹿を呼ぶことには反対です。
ジムシューベルト

3
私は賛成派ではありませんが、別の名前でビューを呼び出すか、パラメータが重要である場合、それらは失われます。その理由は、URLがサーバー側のリダイレクト前のアクションとパラメーターを反映するためです。これにより、ユーザーが混乱する可能性があります。特に、ユーザーがページを更新した後、前のページに戻った場合(更新により古いURLが使用されたため)。この手法は本質的にasp.netのServer.Transferと非常によく似ており、同じ注意を払う必要があります。
AaronLS

15
私はそれ自体は投票しませんでしたが、理由はわかります。このメソッドは、MVCパターンで設定されたコーディング規約に違反します。同じアクションを呼び出すときにのみ機能します。アクションが別の場合、同じコントローラーでも、ルーティング値がねじ込まれ、誤ったビューが返されます。つまり、これを行わないでください。
erlando 2012

21

クエリ文字列にデータを含めずに、リダイレクト中に2つのアクション間でデータを渡す場合は、モデルをTempDataオブジェクトに配置します。

アクション

TempData["datacontainer"] = modelData;

見る

var modelData= TempData["datacontainer"] as ModelDataType; 

TempDataは非常に短期間のインスタンスであることを意図しており、現在のリクエストと後続のリクエストでのみ使用してください。TempDataはこのように機能するため、次のリクエストがどうなるかを確実に知る必要があり、別のビューへのリダイレクトがこれを保証できる唯一の時間です。

したがって、TempDataを確実に使用できる唯一のシナリオは、リダイレクトする場合です。


11

これを試して

return Content("<form action='actionname' id='frmTest' method='post'><input type='hidden' name='someValue' value='" + someValue + "' /><input type='hidden' name='anotherValue' value='" + anotherValue + "' /></form><script>document.getElementById('frmTest').submit();</script>");

2
それを憎むがそれを愛する:)
divinci

そのようなハックですが、DRYに違反したり、セットアップ全体を再配線したりせずに、私が望んだことを実行できる唯一の方法でした!ありがとう!
jamheadart

6

Jason Buntingの答えを広げたい

このような

ActionResult action = new SampelController().Index(2, "text");
return action;

そして、イーライは、それをジェネリック変数にする方法に関するアイデアのためにここにいます

すべてのタイプのコントローラーを入手できます


new ...()が失われるため、コントローラのインスタンスを作成しないでRequestContextください。すでに同じコントローラにいる場合は、新しいインスタンスを作成する必要がない場合があります。それ以外の場合は、次の方法を使用します。SampelController sampleController = DependencyResolver.Current.GetService<SampelController>()その後、ヒントsampleController.ControllerContext = new ControllerContext(Request.RequestContext, sampleController);を表示できますreturn sampleController.Index(2, "text");:)
Matthias Burger
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.