送信ボタンが押されたMVC


127

MVCフォームに2つのボタンがあります。

<input name="submit" type="submit" id="submit" value="Save" />
<input name="process" type="submit" id="process" value="Process" />

コントローラーアクションから、どのキーが押されたかを知るにはどうすればよいですか?


適切なメソッドに移動する独自のAJAX呼び出しに移動するこれらのボタンにonclickイベントを追加しないのはなぜですか?すなわち:<input name="submit" type="submit" id="submit" value="Save" onclick="saveMethod" />
飼育場2015年

回答:


168

両方の送信ボタンに同じ名前を付けます

<input name="submit" type="submit" id="submit" value="Save" />
<input name="submit" type="submit" id="process" value="Process" />

次に、コントローラーでsubmitの値を取得します。クリックされたボタンのみがその値を渡します。

public ActionResult Index(string submit)
{
    Response.Write(submit);
    return View();
}

もちろん、その値を評価して、switchブロックでさまざまな操作を実行できます。

public ActionResult Index(string submit)
{
    switch (submit)
    {
        case "Save":
            // Do something
            break;
        case "Process":
            // Do something
            break;
        default:
            throw new Exception();
            break;
    }

    return View();
}

13
ローカリゼーションがこのソリューションにもたらす可能性がある問題に注意してください。Darinのソリューションは影響を受けません。
Richard Szalay、

同じ名前の2つの入力は、暗黙の単一の値ではなく、値ごとに1つの要素を持つ配列がポストされます。これを使用したいと思っていたので、別の言い方をしたいと思いますが、これは機能しません。
クリストファーキング

1
@RichardSzalay- <button type="submit" name="action" value="draft"> Internationalized Save Text </button>i18nの目的で使用できないので、ユーザー向けの文字列はカスタマイズ可能であり、フォーム要素名がユーザーに直接公開されることはありません(これ自体は奇妙です)
KyleMit

48
<input name="submit" type="submit" id="submit" value="Save" />
<input name="process" type="submit" id="process" value="Process" />

そしてあなたのコントローラーアクションで:

public ActionResult SomeAction(string submit)
{
    if (!string.IsNullOrEmpty(submit))
    {
        // Save was pressed
    }
    else
    {
        // Process was pressed
    }
}

1
パラメータリストにボタンを追加し、正しく名前を付けるだけで、ボタンを追加できると思います。素敵な解決策!
GONeale 2011

35

これはより良い答えなので、ボタンのテキストと値の両方を持つことができます:

http://weblogs.asp.net/dfindley/archive/2009/05/31/asp-net-mvc-multiple-buttons-in-the-same-form.aspx

</p>
<button name="button" value="register">Register</button>
<button name="button" value="cancel">Cancel</button>
</p>

そしてコントローラー:

public ActionResult Register(string button, string userName, string email, string password, string confirmPassword)
{
if (button == "cancel")
    return RedirectToAction("Index", "Home");
...

つまり、SUBMITボタンですが、name属性を使用して名前を選択します。コントローラーメソッドのパラメーターで名前の送信またはボタンを義務付けられていないので、好きなように呼び出すことができます...


おかげ卿は、これは私が必要なものを正確に
oHoodie

言語に応じてボタンの値を変更する多言語システムを使用している場合、これは機能しません。
Dave Tapson

Dave-そのようなシステムをコーディングする人は誰もいないと思います。これは、コントローラー名や関数名をローカライズするようなものです。ボタンのはサーバー側でのみ使用します。どこにも表示されず、ローカライズする必要はありません。
NickG

20

以下のような名前タグからボタンを識別できます。コントローラでこのように確認する必要があります

if (Request.Form["submit"] != null)
{
//Write your code here
}
else if (Request.Form["process"] != null)
{
//Write your code here
}

これは、ボタンの名前をアクション後の結果に渡したくない場合に非常に役立ちます。
yogihosting 2017

このシナリオでは、単体テストでRequestクラスをモックするのがより複雑になる可能性があります。
Muflix、2017年

6

これは、カスタムMultiButtonAttributeを使用して非常に簡単に実行できる指示を使用して実行する、とても素晴らしくシンプルな方法です。

http://blog.maartenballiauw.be/post/2009/11/26/Supporting-multiple-submit-buttons-on-an-ASPNET-MVC-view.aspx

要約すると、次のように送信ボタンを作成します。

<input type="submit" value="Cancel" name="action" />
<input type="submit" value="Create" name="action" /> 

このようなあなたの行動:

[HttpPost]
[MultiButton(MatchFormKey="action", MatchFormValue="Cancel")]
public ActionResult Cancel()
{
    return Content("Cancel clicked");
}

[HttpPost]
[MultiButton(MatchFormKey = "action", MatchFormValue = "Create")]
public ActionResult Create(Person person)
{
    return Content("Create clicked");
} 

そして、このクラスを作成します:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultiButtonAttribute : ActionNameSelectorAttribute
{
    public string MatchFormKey { get; set; }
    public string MatchFormValue { get; set; }

    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
    {
        return controllerContext.HttpContext.Request[MatchFormKey] != null &&
            controllerContext.HttpContext.Request[MatchFormKey] == MatchFormValue;
    }
}

1
参照されているリンクを要約することは常に最善です(ブログが消える日のために)。要約すると、ブログではMultiButtonAttribute、送信ボタンを区別できるカスタム属性を推奨しています。実際にはかなり良いアイデアです。
コーディング終了

1
そしてArnis L.、同じアドバイスに従ったなら、彼は4年前にまったく同じリンクを提供したことに気づいたかもしれません:>
Gone Coding

3
// Buttons
<input name="submit" type="submit" id="submit" value="Save" />
<input name="process" type="submit" id="process" value="Process" />

// Controller
[HttpPost]
public ActionResult index(FormCollection collection)
{
    string submitType = "unknown";

    if(collection["submit"] != null)
    {
        submitType = "submit";
    }
    else if (collection["process"] != null)
    {
        submitType = "process";
    }

} // End of the index method

これは、非常に複雑なフォームデータを各アクションでカスタマイズされたパラメーターセットなしで一貫して渡すことができ、コントローラーロジックを複雑なフォーム用に高度にカスタマイズできるため、他のすべての投稿よりも優れたソリューションです。Kudos Fredrik :)このFormCollectionは複数のフォームで渡されると思いますか?
Stokely 2017

Stokelyに感謝します。このメソッドは複数のフォームから呼び出すことができます。ajax呼び出しを行うと、同じFormCollectionに多くのフォームを含めることができます。
Fredrik Stigsson 2017

3

簡単にするために、ボタンを次のように変更できます。

<input name="btnSubmit" type="submit" value="Save" />
<input name="btnProcess" type="submit" value="Process" />

あなたのコントローラー:

public ActionResult Create(string btnSubmit, string btnProcess)
{
    if(btnSubmit != null)
       // do something for the Button btnSubmit
    else 
       // do something for the Button btnProcess
}

2

彼がずっと前に答え​​られたので、この投稿はコッパーミルに答えません。私の投稿は、このような解決策を模索する人に役立ちます。まず、「WDuffyのソリューションは完全に正しい」と言わなければなりません。それは正常に機能しますが、私のソリューション(実際には私のソリューションではありません)は他の要素で使用され、プレゼンテーションレイヤーをコントローラーからより独立させます(コントローラーが依存しているため)ボタンのラベルを示すために使用される「値」。この機能は他の言語にとって重要です。)

ここに私の解決策があります、それらに異なる名前を付けます:

<input type="submit" name="buttonSave" value="Save"/>
<input type="submit" name="buttonProcess" value="Process"/>
<input type="submit" name="buttonCancel" value="Cancel"/>

また、次のようなアクションの引数としてボタンの名前を指定する必要があります。

public ActionResult Register(string buttonSave, string buttonProcess, string buttonCancel)
{
    if (buttonSave!= null)
    {
        //save is pressed
    }
    if (buttonProcess!= null)
    {
        //Process is pressed
    }
    if (buttonCancel!= null)
    {
        //Cancel is pressed
    }
}

ユーザーがいずれかのボタンを使用してページを送信すると、1つの引数のみが値を持ちます。これは他の人に役立つと思います。

更新

この答えはかなり古く、私は実際に私の考えを再考します。おそらく上記の解決策は、モデルのプロパティにパラメータを渡す状況に適しています。気にせず、プロジェクトに最適なソリューションを採用してください。


いくつかの建設的な批判:これは、これを投稿した時点での既存の回答で十分にカバーされています。さらに、これはうまく拡張できません。HTML input[type=submit]はトリガーされた値のみをポストバックするため、それらはすべて同じname(たとえばaction)のプロパティにバインドできvalue、その文字列に基づいてボタンを区別できます。署名に多くの変数を導入する必要はありません。。投稿する前に、フォーマット/インデントについても検討してください。
KyleMit

0

Request.Formコレクションを使用して見つけることができませんか?プロセスをクリックすると、request.form ["process"]は空になりません


0

両方のボタンに名前を付け、フォームから値を確認します。

<div>
   <input name="submitButton" type="submit" value="Register" />
</div>

<div>
   <input name="cancelButton" type="submit" value="Cancel" />
</div>

コントローラ側:

public ActionResult Save(FormCollection form)
{
 if (this.httpContext.Request.Form["cancelButton"] !=null)
 {
   // return to the action;
 }

else if(this.httpContext.Request.Form["submitButton"] !=null)
 {
   // save the oprtation and retrun to the action;
 }
}

0

Core 2.2 Razorページでは、この構文は機能します。

    <button type="submit" name="Submit">Save</button>
    <button type="submit" name="Cancel">Cancel</button>
public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
        return Page();
    var sub = Request.Form["Submit"];
    var can = Request.Form["Cancel"];
    if (sub.Count > 0)
       {
       .......

それはうまくいくかもしれませんが、私はstring submit書くよりもパラメータを好みますstring submit = Request.Form["Submit"];。RazorページやMVCの最大の利点の1つは、メソッドの読みやすさです。それ以外の場合は、PHPになる可能性があります。
yzorg
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.