Online courses in ASP.NET MVC, ASP.NET Core, and Design Patterns conducted by Bipin Joshi. Read more...
Learn ASP.NET MVC, ASP.NET Core, and Design Patterns through our online training programs. Courses conducted by Bipin Joshi on weekends. Read more details here.

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.




Bipin Joshi is a software consultant, trainer, author and a yogi having 21+ years of experience in software development. He conducts online courses in ASP.NET MVC / Core, jQuery, AngularJS, and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced Yoga way of life he also teaches Ajapa Meditation to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 05 Oct 2015



Tags : ASP.NET MVC C#