HTTPPOST、ディクショナリまたはフォームからフォームの値を取得する方法


111

このアクションメソッドを持つMVCコントローラーがあります。

[HttpPost]
public ActionResult SubmitAction()
{
     // Get Post Params Here
 ... return something ...
}

フォームは、単純なテキストボックスを持つ重要なフォームです。

質問

パラメータ値にアクセスするにはどうすればよいですか?

ビューから投稿するのではなく、投稿は外部から行われます。アクセスできるキー/値ペアのコレクションがあると想定しています。

試しRequest.Params.Get("simpleTextBox");たところ、「申し訳ありませんが、リクエストの処理中にエラーが発生しました。」というエラーが返されました。

回答:


155

コントローラーのアクションで、フォームの入力名を反映するオブジェクトを実行させると、デフォルトのモデルバインダーがこのオブジェクトを自動的に作成します。

[HttpPost]
public ActionResult SubmitAction(SomeModel model)
{
    var value1 = model.SimpleProp1;
    var value2 = model.SimpleProp2;
    var value3 = model.ComplexProp1.SimpleProp1;
    ...

    ... return something ...
}

別の(明らかに醜い)方法は:

[HttpPost]
public ActionResult SubmitAction()
{
    var value1 = Request["SimpleProp1"];
    var value2 = Request["SimpleProp2"];
    var value3 = Request["ComplexProp1.SimpleProp1"];
    ...

    ... return something ...
}

5
オプション2でコンパイラーのバックアップが失われることを指摘しておきます。モデルが変更されると、コンパイラーは関連するコントローラーの変更をキャッチしません。オプション2には適切なケースがありますが、広く使用することはお勧めしません。
セルゲイフェドロフ

1
ときどき醜いものが必要ですが、ベストプラクティスがすでにわかっている場合は選択肢を用意するとよいでしょう
Oscar Ortiz

まだドットネットを学習している人として、なぜ第2の方法が醜いのですか?
グース

3
@Goose、それは魔法の文字列だからです。コンパイル時の安全性は得られません。変数の名前にタイプミスがあると、コードは実行時に失敗しますが、強い型付けを使用している場合は、コンパイラーが役に立ちます。
Darin Dimitrov

@DarinDimitrovは理にかなっています。私の出身の世界とは異なります。とても素敵な機能。
2017年

104

簡単に言うと、次のFormCollectionように使用できます。

[HttpPost] 
public ActionResult SubmitAction(FormCollection collection)
{
     // Get Post Params Here
 string var1 = collection["var1"];
}

Form値でマップされたクラスを使用することもできます。asp.netmvcエンジンが自動的に入力します。

//Defined in another file
class MyForm
{
  public string var1 { get; set; }
}

[HttpPost]
public ActionResult SubmitAction(MyForm form)
{      
  string var1 = form1.Var1;
}

私はクラスソリューションが簡単でシンプルなのが好きでした
Basheer AL-MOMANI 2016

36

答えはとても良いですが、MVCと.NETの最新リリースには、「古い学校」のFormCollectionキーとRequestキーの代わりに、本当に使いたい別の方法があります。


AJAXまたはFORM POSTを実行するformタグ内に含まれるHTMLスニペットを考えてみます。

<input type="hidden"   name="TrackingID" 
<input type="text"     name="FirstName"  id="firstnametext" />
<input type="checkbox" name="IsLegal"  value="Do you accept terms and conditions?" />

コントローラは実際にフォームデータを解析し、定義されたタイプのパラメータとしてそれを配信しようとします。トリッキーなのでチェックボックスを入れました。チェックされている場合はテキスト「on」を返し、チェックされていない場合はnullを返します。ただし、これらの定義された変数が存在しなければならない(nullableでない限り(nullableであることを覚えておいてくださいstring))必要があります。そうでない場合、AJAXまたはPOSTバックは失敗します。

[HttpPost]
public ActionResult PostBack(int TrackingID, string FirstName, string IsLegal){
    MyData.SaveRequest(TrackingID,FirstName, IsLegal == null ? false : true);
}

かみそりヘルパーを使用せずにモデルをポストバックすることもできます。これが何度か必要になることを知りました。

public Class HomeModel
{
  public int HouseNumber { get; set; }
  public string StreetAddress { get; set; }
}

HTMLマークアップは単に...

<input type="text" name="variableName.HouseNumber" id="whateverid" >

そして、コントローラー(Razor Engine)は、フォーム変数「variableName」(名前は好きなようですが、一貫性を保ちます)をインターセプトし、それを構築してMyModelにキャストしようとします。

[HttpPost]
public ActionResult PostBack(HomeModel variableName){
    postBack.HouseNumber; //The value user entered
    postBack.StreetAddress; //the default value of NULL.
}

コントローラーがモデル(この場合はHomeModel)を期待している場合、パーサーはフィールドをデフォルト(通常はNULL)のままにするため、すべてのフィールドを定義する必要はありません。良い点は、マークアップでさまざまなモデルを混合して一致させることができ、ポストバック解析が可能な限り読み込まれることです。ページでモデルを定義したり、ヘルパーを使用したりする必要はありません。

ヒント:コントローラーのパラメーターの名前は、HTMLマークアップ「name = "で定義された名前であり、モデルの名前ではなく、!


List<>マークアップの使い方は少し複雑です。

<input type="text" name="variableNameHere[0].HouseNumber" id="id"           value="0">
<input type="text" name="variableNameHere[1].HouseNumber" id="whateverid-x" value="1">
<input type="text" name="variableNameHere[2].HouseNumber"                   value="2">
<input type="text" name="variableNameHere[3].HouseNumber" id="whateverid22" value="3">

List <>のインデックスは常にゼロベースでシーケンシャルでなければなりません。0、1、2、3。

[HttpPost]
public ActionResult PostBack(List<HomeModel> variableNameHere){
     int counter = MyHomes.Count()
     foreach(var home in MyHomes)
     { ... }
}

IEnumerable<>非ゼロベースの非連続インデックスにポストバックを使用します。バインダーを支援するために、隠し入力を追加する必要があります。

<input type="hidden" name="variableNameHere.Index" value="278">
<input type="text" name="variableNameHere[278].HouseNumber" id="id"      value="3">

<input type="hidden" name="variableNameHere.Index" value="99976">
<input type="text" name="variableNameHere[99976].HouseNumber" id="id3"   value="4">

<input type="hidden" name="variableNameHere.Index" value="777">
<input type="text" name="variableNameHere[777].HouseNumber" id="id23"    value="5">

そして、コードはIEnumerableを使用して呼び出すだけです ToList()

[HttpPost]
public ActionResult PostBack(IEnumerable<MyModel> variableNameHere){
     int counter = variableNameHere.ToList().Count()
     foreach(var home in variableNameHere)
     { ... }
}

ページごとに単一のモデルまたはViewModel(複雑な「ビュー」モデルを作成するために他のモデルを含むモデル)を使用することをお勧めします。提案どおりの混合とマッチングは悪い習慣と見なすことができますが、それが機能し、読み取り可能である限り、それは悪いことではありません。ただし、Razorエンジンのパワーと柔軟性を示しています。

したがって、何かをドロップするか、Razorヘルパーから別の値をオーバーライドする必要がある場合、または独自のヘルパーを作成したくない場合は、データの異常な組み合わせを使用する単一のフォームで、これらのメソッドをすばやく使用して追加を受け入れることができますデータ。


インデックスオプションの使用はあいまいです。神の緑の地球の誰がそれを使用することを知っていたか、それが存在することさえ知っていただろうか。しかし、私はこの投稿を見つけてうれしいです。これにより、ネットワークトラフィックが大幅に節約されます。
マイケルシルバー

1
これは私にとってはうまくいきましたが、<input type = "hidden" id = "myId">を@ Html.Hidden( "myId")に変更した後にのみ
radkan

@Piotr-MyModelおよびMyHomesとの参照の不整合を修正してください。現在の状態が混乱しています。
スペンサーサリバン

15

モデルバインディングなしでHttpリクエストから直接フォームデータを取得する場合、またはFormCollectionこれを使用できます。

[HttpPost] 
public ActionResult SubmitAction() {

    // This will return an string array of all keys in the form.
    // NOTE: you specify the keys in form by the name attributes e.g:
    // <input name="this is the key" value="some value" type="test" />
    var keys = Request.Form.AllKeys;

    // This will return the value for the keys.
    var value1 = Request.Form.Get(keys[0]);
    var value2 = Request.Form.Get(keys[1]);
}

2
これは不適切なフォームである可能性があります(しゃれは意図されていません)が、フォームの値が必要なだけで、関数のシグネチャを明確に変更できない場合があることに注意してください。これは、私の特定の状況に適した唯一のソリューションです。
ライアン

これらの静的参照を使用してこのメ​​ソッドを単体テストするにはどうすればよいですか?テストに関しては、FormCollectionの方が望ましいでしょう。
Kees de Wit 2017年

@KeesdeWit以前のコメントを読んだ場合、これは最善の方法ではありませんが、回避策として使用する場合があります。単体テストを行うには、おそらくをモックRequestしてメソッドに注入できます。
A-Sharabiani 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.