Freigeben über


Detecting which button was clicked in MVC

I’ve seen a few hacks in the past to try and work out which button caused a form POST in ASP.NET MVC, but the truth is it is pretty easy.

Step 1: Inside your form, add two Submit buttons. Add a name attribute to both (note it isn’t added by MVC by default);

    1:  <p>
    2:      <input type="submit" name="Command" value="Save" />
    3:      <input type="submit" name="Command" value="Delete" />
    4:  </p>

Note both have the same name.

Step 2: Inside your action, add a parameter that matches the name of the buttons;

    1:  [HttpPost]
    2:  public ActionResult Index(
    3:      Person person, 
    4:      string command)
    5:  {
    6:      bool saved = (command == "Save");
    7:   
    8:      if (saved)
    9:          // code removed
   10:      else
   11:          // code removed
   12:  }

Simple huh? You could write some clever extension method to inspect the posted HTTP values, but I find this approach far more elegant. It is really clear that I’m expecting the “command” to be posted to my action.

A part of me wonders if naming all your buttons the same contravenes the HTML specification, but I can find no evidence of this – it is an accepted practice for checkboxes and radio buttons of course, and I’ve found this to work well. If you know otherwise do shout up. Like it? Hate it?

Step 3: Well… let’s take it one step further and create an enum of commands;

    1:  public enum Command
    2:  {
    3:      Save,
    4:      Delete
    5:  }

Step 4: … and update our action method parameter’s type to be our new enum, and of course our logic to use it;

    1:  [HttpPost]
    2:  public ActionResult Index(
    3:      Person person, 
    4:      Command command)
    5:  {
    6:      if (command == Command.Save)
    7:          // code removed
    8:      else
    9:          // code removed
   10:  }

Hey presto! Strongly typed clear code that reacts to which button was clicked.

Comments

  • Anonymous
    February 12, 2011
    You might want to try that in all browsers.

  • Anonymous
    February 12, 2011
    @ Nick; I agree, which is why I called out the question about HTML specs - but I've seen no issues in the past on any browser. I have FireFox, IE, and Chrome on my machine and just retested it in case something had changed, but had no problem... Do you know of a browser that it doesn't work with? Simon

  • Anonymous
    February 13, 2011
    Simon, I have been using this attribute which seems to cater well for multi submit forms. blog.maartenballiauw.be/.../Supporting-multiple-submit-buttons-on-an-ASPNET-MVC-view.aspx Regards

  • Anonymous
    February 13, 2011
    @ George; Good find, I like it. It's very similar to how I split Ajax/Non-Ajax actions (i.e. it is an ActionMethodSelectorAttribute). I guess I'd probably use these approaches in slightly different circumstances, depending upon what the action needs to do. Of course, the perfect way to do this is to have separate forms altogether (that point at different actions), so we should highlight that as a third way. These two other approaches are for times when that won't work. Simon

  • Anonymous
    December 14, 2012
    Thanks a ton, you saved my lots of time.. I was nailing for that...!!

  • Anonymous
    February 05, 2013
    I try it, but it doesn't work in chrome... Value attribute doesn't post from browser to controller

  • Anonymous
    February 07, 2013
    Depending on what you need, you could also do nested forms or multiple forms.  In the case of Delete, for example, all you really need to know is the ID of the article to delete.  Create a hidden input for that ID, and add a new form that posts to a different method on the controller.  It's kind of funny how asp.NET eliminated the ability to have multiple forms and MVC brings the capability back but no one thinks of using it. The only useful situation for the solution mentioned here is when you want to pass the whole model into separate controllers.  Ask, "Why would this need to be done?"  E.g., some examples mention a 'publish' or 'save' button, and that does make sense, but you could also just have a checkbox that says "publish".  Or, use true ajax and post back to the different controllers (keeps the user on the same page).

  • Anonymous
    June 30, 2013
    we just applied , thanks. saved us , showed the path.