MVC已按下哪个提交按钮


127

我的MVC表单上有两个按钮:

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

从我的控制器动作中,我如何知道哪一个被按下了?


为什么不只在这些按钮上添加onclick事件,这些事件将转到它们自己的AJAX调用,而这些调用将转到相应的方法?即:<input name="submit" type="submit" id="submit" value="Save" onclick="saveMethod" />
拉格里

Answers:


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();
}

您当然可以评估该值,以通过开关块执行不同的操作。

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的解决方案对此并不敏感。
理查德·萨雷

具有相同名称的两个输入将导致发布一个数组,其中每个值包含一个元素,而不是隐含的单个值。所以我希望我可以说别的,因为我一直希望/尝试使用它,但这是行不通的。
克里斯托弗·金

1
@RichardSzalay-您不能仅<button type="submit" name="action" value="draft"> Internationalized Save Text </button>用于i18n用途,因此面向用户的字符串是可自定义的,而且表单元素名称也永远不会直接向用户公开(本身
就很

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

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'3

如果您有一个多语言系统,该系统会根据语言更改按钮的值,则会中断此操作。
戴夫·塔普森

戴夫-我认为没有人会编码这样的系统。这就像本地化控制器名称或函数名称。该按钮的仅用于服务器端-它不会显示在任何地方,也不需要进行本地化。
NickG

20

您可以从那里的名称标签(如下所示)中识别按钮,您需要在控制器中进行检查

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

当您不想将按钮的名称传递到post actionresult时,这非常有用。
yogihosting

在这种情况下,在单元测试中模拟Request类可能会更加复杂。
Muflix '17

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自定义属性以允许区分提交按钮。其实是个不错的主意。
去编码2014年

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

谢谢斯托克。您可以从多种形式调用此方法,如果您进行ajax调用,则可以在同一FormCollection中包含许多形式。
弗雷德里克·斯蒂格森

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

这篇文章将不会回答Coppermill,因为他很久以前就已经回答了。我的帖子对寻求类似解决方案的人会有所帮助。首先,我必须说“ 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
    }
}

当用户使用其中一个按钮提交页面时,只有一个参数具有值。我想这对其他人会有帮助。

更新资料

这个答案很老,我实际上是在重新考虑我的看法。也许上述解决方案对于将参数传递给模型属性的情况很有用。不要为自己的项目而烦恼并采取最佳解决方案。


提出了一些建设性的批评:在您发布此内容时,现有答案已很好地涵盖了这一点。此外,这不能很好地扩展。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 Pages和/或MVC的最大好处之一就是方法的可读性,否则可以是PHP。
yzorg
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.