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");
   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.


Original post by Simon Ince on 02-12-2011 here:

Comments (2)

  1. Joakim Dahl says:

    On issue with this solution is for multilingual sites since the value is the localized string. In that scenario you need to compare with the localized string in your controller.

  2. ukadc says:

    Yes, that’s correct. I guess there’s a few ways you could look at improving that story (perhaps a custom attribute on the enum and a model binder that looks for it) but out-of-the-box I don’t believe there’s anything to help.