【问题标题】:MVC which submit button has been pressed已按下提交按钮的 MVC
【发布时间】:2010-12-15 09:39:11
【问题描述】:

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

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

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

【问题讨论】:

  • 为什么不将 onclick 事件添加到这些按钮,这些按钮将转到它们自己的 AJAX 调用,这些调用将转到它们相应的方法?即:&lt;input name="submit" type="submit" id="submit" value="Save" onclick="saveMethod" /&gt;?

标签: c# asp.net asp.net-mvc razor


【解决方案1】:

这篇文章不会回复 Coppermill,因为他很久以前就得到了回复。我的帖子将对寻求此类解决方案的人有所帮助。首先,我不得不说“WDuffy 的解决方案是完全正确的”,它工作正常,但我的解决方案(实际上不是我的)将用于其他元素,它使表示层更加独立于控制器(因为你的控制器依赖于“value”,用于显示按钮的标签,此功能对于其他语言很重要。)。

这是我的解决方案,给它们起不同的名字:

<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 区分按钮字符串,而无需在您的签名中引入那么多变量。还请在发布前花一些时间考虑格式/缩进。
【解决方案2】:

在 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。
【解决方案3】:

为两个按钮命名并从表单中获取检查值。

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

【讨论】:

    【解决方案4】:

    您可以从下面的名称标签中识别您的按钮, 你需要在你的控制器中这样检查

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

    【讨论】:

    • 这在您不想将按钮名称传递给 post actionresult 的情况下非常有用。
    • 在这种情况下,在单元测试中模拟 Request 类可能会更复杂。
    【解决方案5】:

    将两个提交按钮命名为相同

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

    然后在您的控制器中获取提交的值。只有被点击的按钮才会传递它的值。

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

    【讨论】:

    • 当心本地化可能给这个解决方案带来的问题,达林的解决方案是不敏感的。
    • 两个具有相同名称的输入会导致发布一个数组,其中每个值都有一个元素,而不是隐含的单个值。所以我希望我能说别的,因为我希望/试图使用它,但这不起作用。
    • @RichardSzalay - 你不能只将&lt;button type="submit" name="action" value="draft"&gt; Internationalized Save Text &lt;/button&gt; 用于 i18n 目的,因此面向用户的字符串是可自定义的,并且表单元素名称永远不会直接暴露给用户(这在和本身)
    • 只是一个提示,命名“提交”按钮不是一个好主意:stackoverflow.com/questions/833032/…
    【解决方案6】:

    为了方便起见,我会说您可以将按钮更改为以下内容:

    <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
    }
    

    【讨论】:

      【解决方案7】:
      // 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 会以多种形式传递?
      • 谢谢斯托克利。您可以从多个表单调用此方法,如果您进行 ajax 调用,那么您可以在同一个 FormCollection 中包含多个表单。
      【解决方案8】:

      这是一个非常好的和简单的方法,使用自定义 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;
          }
      }
      

      【讨论】:

      • 总是最好总结一个引用的链接(在博客消失的那一天)。总之,博客提倡使用MultiButtonAttribute 自定义属性来区分提交按钮。其实是个好主意。
      • 如果Arnis L. 遵循了同样的建议,您可能已经注意到他在 4 年前提供了完全相同的链接:>
      【解决方案9】:

      这是一个更好的答案,所以我们可以同时为按钮设置文本和值:

      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 属性选择名称,它更强大,因为您不必在控制器方法参数中指定名称 submit 或按钮,您可以随意调用它...

      【讨论】:

      • 谢谢先生,这正是我需要的
      • 如果你有一个多语言系统,它会根据语言改变按钮的值。
      • Dave - 我认为没有人会编写这样的系统。这就像本地化您的控制器名称或函数名称。按钮的 仅供服务器端使用 - 它不会显示在任何地方,也不需要本地化。
      【解决方案10】:

      你不能用 Request.Form Collection 找出来吗?如果点击流程,request.form["process"] 不会为空

      【讨论】:

        【解决方案11】:
        <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
            }
        }
        

        【讨论】:

        • 我想可以通过简单地将其添加到参数列表并正确命名来添加更多按钮。不错的解决方案!
        猜你喜欢
        • 2014-02-03
        • 2013-12-27
        • 1970-01-01
        • 1970-01-01
        • 2014-08-17
        • 2017-07-14
        • 2015-05-07
        • 2016-10-22
        • 2019-05-27
        相关资源
        最近更新 更多