Overloading Controller Actions in ASP.NET MVC
Method overloading is very common technique used in C# code. Although it
works great for normal C# classes, the same can't be said about ASP.NET MVC
controller classes. If you ever tried to implement method overloading for MVC
actions you are probably aware of the following exception:

Unlike an ordinary C# class, a controller is dealing with HTTP protocol. And
HTTP doesn't understand overloading as C# does. So, in case you wish to use
method overloading in a controller you need to consider the four possible ways
as discussed in the remainder of this article.
Actions handling different HTTP verbs
In this scenario you have two action methods with the same name BUT they
handle different HTTP verbs. Consider the following fragment of code:
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(Customer obj)
{
//do something with obj
return View();
}
As you can see the first Index() action deals with the GET requests whereas
the second Index() action deals with POST requests. The first version is
parameter-less whereas the second accepts a parameter of type Customer (this
depends on what you are submitting from the view. The above example assumes you
are submitting customer data).
The above overloaded methods work fine since each is dealing with different
HTTP verb.
Actions handling GET requests and attribute routing
You can overload actions dealing with GET requests if you configure attribute
routing properly. The following example will make this clear:
[Route("Home/DoWork/{status:int}")]
public ActionResult DoWork(int status)
{
return View();
}
[Route("Home/DoWork/{flag:bool}")]
public ActionResult DoWork(bool flag)
{
return View();
}
Now in this case there are two DoWork() actions but one has an integer
parameter whereas the other has a boolean parameter. Moreover, [Route] attribute
is used to configure attribute based routing. Notice that the first [Route]
attribute specifies that status parameter is int and the second specifies that
it is bool. So, if a URL is /home/dowork/10 then it will be handled by the first
DoWork() whereas if the URL is /home/dowork/true it will be handled by the
second DoWork() action.
Make sure you call MapMvcAttributeRoutes() in the RouteConfig.cs file before
you test this technique.
Overloaded actions marked as [NonAction]
In this technique you create a public action method as usual. And then create
several overloads of it as that are not MVC actions. These overloads are marked as [NonAction]
attribute. The following code fragment will make it clear:
[HttpPost]
public ActionResult Calculate()
{
int i = int.Parse(Request.Form["num1"]);
int j = int.Parse(Request.Form["num2"]);
return Calculate(i , j);
}
[NonAction]
public ActionResult Calculate(int i, int j)
{
return View( i + j );
}
Here, the first method - Calculate() - acts as an MCV action method. The
Calculate() then invokes an overload - Calculate(int,int). The overload does its
job and returns a view to the caller. Notice that the second Calculate() is
marked with [NonAction] attribute. The [NonAction] attribute indicates that the
method under consideration should not be treated as an action. Since the method
is no longer an action it doesn't interfere in the working of HTTP and the
controller.
[ActionName] attribute
In this technique you create overloaded action methods as you would
have done in any C# class. But give them another unique name using the [ActionName]
attribute. The following code fragment will make it clear:
[HttpPost]
[ActionName("ProcessForm1")]
public ActionResult ProcessForm(Customer obj)
{
return View();
}
[HttpPost]
[ActionName("ProcessForm2")]
public ActionResult ProcessForm(Employee emp)
{
return View();
}
Here, we have two overloads of the ProcessForm() actions. However, both have
[ActionName] attribute added on top of them. The [ActionName] attribute assigns
a unique name to a method that is then used by the MVC framework. That means for
your C# code the method name remains ProcessForm() but for the MVC framework
(including routing engine and HTML helpers) they represent two methods -
ProcessForm1() and ProcessForm2().
Remember that when you use [ActionName] attribute you are assigning a
different name to the action method under consideration. In helpers such as
BeginForm() and ActionLink() you should use the name as defined in the [ActionName]
attribute (ProcessForm1 and ProcessForm2 in this case).
That's it! Although it is better to keep away from method overloading in the
controllers, if at all you wish to implement overloading you can use one of the
above ways. As you can see using overloading adds a bit of complexity to your
controller. But it is possible in a limited way if needed.