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? SimonAnonymous
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 RegardsAnonymous
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. SimonAnonymous
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 controllerAnonymous
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.