Abstract: The following article demonstrates how to use the ActionMethodSelectorAttribute object to handle multiple submit buttons with ASP.NET MVC.

My first article in this series focused on how to have Multiple submit buttons in the same ASP.NET MVC form, and how to differentiate them in your action method. If you missed it you can read it here. The second part focused on how to do this with Ajax. If you want to hijack your form and post it via Ajax, you need to do some extra work. Controls that have a name attribute are posted as part of the form because they’re a successful control. However when you use Ajax to post a form, only successful controls are serialized into string. Submit buttons aren’t serialized seeing as though the form wasn’t submitted using a button.

To take this example to the next level, I’m removing the if/else logic from the action and am placing all of that logic into an action filter that inherits from the ActionMethodSelectorAttribute. I did an article on using this class here. It showed you how to restrict access to actions. Well this is what I’m going to do in this example.

I’m using the same form as I used in the previous articles.

I’ll start off with the attribute I will decorate my actions with. I’m creating a class that inherits from ActionMethodSelectorAttribute. The first parameter is ControllerContext. This parameter will contain, amongst other objects, the FormValueProvider object. This contains values posted in the form in a NameValueCollection object. This is what I’ll check to see which button submitted the form. Here’s the code below. Nice and compact.

The next step is to create two action methods, Save and Delete. To ensure that either of these actions will be invoked, I’m going to decorate them with the ActionName attribute. This gives you the flexibility of having different actions but still allowing you to access them with a common name. The common name is PostData.

If you tried running the website now, you’ll see this error:

System.Reflection.AmbiguousMatchException: The current request for action 'PostData' on controller type 'HomeController' is ambiguous between the following action methods.

This is because we have two actions decorated with the same ActionName. That isn’t allowed. We need to restrict access to one action only, and we’ll use the ButtonAttribute class for this. I want to decorate my actions with this attribute and supply a ButtonName.

Because this attribute will be executed before the action, it can check the values in the FormValueProvider and see if they match the value specified on the attribute. If posted form contains a value that matches the value in ButtonName, IsValidForRequest returns true, thus the proper action will be invoked.

When the Save button is clicked, a new hidden input named Save will be injected into the form and that will be sent in the forms collection. This is why when you click on the Save submit button, you’ll be directed to the Save action. The same rule applies for the Delete submit button. Here’s the JavaScript to do this.

It’s important to remember that injecting the hidden inputs is not required if the form is submitted without JavaScript. This is another good example of when to use ActionMethodSelectorAttribute.

The entire source code of this article can be downloaded over here

This article has been editorially reviewed by Suprotim Agarwal.

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn. We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle). Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview. Click here to Explore the Table of Contents or Download Sample Chapters!