I\'m curious to see if you can overload controller methods in ASP.NET MVC. Whenever I try, I get the error below. The two methods accept different arguments. Is this some
I've just come across this question and, even though it's quite old now, it's still very relevant. Ironically, the one correct comment in this thread was posted by a self-confessed beginner in MVC when he wrote the post. Even the ASP.NET docs are not entirely correct. I have a large project and I successfully overload action methods.
If one understands routing, beyond the simple {controller}/{action}/{id} default route pattern, it might be obvious that controller actions can be mapped using any unique pattern. Someone here talked about polymorphism and said: "HTTP does not understand polymorphism", but routing has nothing to do with HTTP. It is, simply put, a mechanism for string pattern matching.
The best way to make this work is to use the routing attributes, for example:
[RoutePrefix("cars/{country:length(3)}")]
public class CarHireController
{
[Route("{location}/{page:int=1}", Name = "CarHireLocation")]
public ActionResult Index(string country, string location, int page)
{
return Index(country, location, null, page);
}
[Route("{location}/{subLocation}/{page:int=1}", Name = "CarHireSubLocation")]
public ActionResult Index(string country, string location, string subLocation, int page)
{
//The main work goes here
}
}
These actions will take care of urls like /cars/usa/new-york
and /cars/usa/texas/dallas
, which will map to the first and second Index actions respectively.
Examining this example controller it's evident that it goes beyond the default route pattern mentioned above. The default works well if your url structure exactly matches your code naming conventions, but this is not always the case. Code should be descriptive of the domain, but urls often need to go further because their content should be based on other criteria, such as SEO requirements.
The benefit of the default routing pattern is that it automatically creates unique routes. This is enforced by the compiler since urls will match unique controller types and members. Rolling your own route patterns will require careful thought to ensure uniqueness and that they work.
Important note The one drawback is that using routing to generate urls for overloaded actions does not work when based on an action name, e.g., when using UrlHelper.Action. But it does work if one uses named routes, e.g., UrlHelper.RouteUrl. And using named routes is, according to well respected sources, the way to go anyhow (http://haacked.com/archive/2010/11/21/named-routes-to-the-rescue.aspx/).
Good luck!
Here's something else you could do... you want a method that is able to have a parameter and not.
Why not try this...
public ActionResult Show( string username = null )
{
...
}
This has worked for me... and in this one method, you can actually test to see if you have the incoming parameter.
I have faced same issue in my application too. Without Modifiyig any Method information, I have provided [ActionName("SomeMeaningfulName")] on Action head. issue resolved
[ActionName("_EmployeeDetailsByModel")]
public PartialViewResult _EmployeeDetails(Employee model)
{
// Some Operation
return PartialView(model);
}
}
[ActionName("_EmployeeDetailsByModelWithPagination")]
public PartialViewResult _EmployeeDetails(Employee model,int Page,int PageSize)
{
// Some Operation
return PartialView(model);
}
No,No and No. Go and try the controller code below where we have the "LoadCustomer" overloaded.
public class CustomerController : Controller
{
//
// GET: /Customer/
public ActionResult LoadCustomer()
{
return Content("LoadCustomer");
}
public ActionResult LoadCustomer(string str)
{
return Content("LoadCustomer with a string");
}
}
If you try to invoke the "LoadCustomer" action you will get error as shown in the below figure.
Polymorphism is a part of C# programming while HTTP is a protocol. HTTP does not understand polymorphism. HTTP works on the concept's or URL and URL can only have unique name's. So HTTP does not implement polymorphism.
In order to fix the same we need to use "ActionName" attribute.
public class CustomerController : Controller
{
//
// GET: /Customer/
public ActionResult LoadCustomer()
{
return Content("LoadCustomer");
}
[ActionName("LoadCustomerbyName")]
public ActionResult LoadCustomer(string str)
{
return Content("LoadCustomer with a string");
}
}
So now if you make a call to URL "Customer/LoadCustomer" the "LoadCustomer" action will be invoked and with URL structure "Customer/LoadCustomerByName" the "LoadCustomer(string str)" will be invoked.
The above answer i have taken from this codeproject article --> MVC Action overloading
To overcome this problem you can write an ActionMethodSelectorAttribute
that examines the MethodInfo
for each action and compares it to the posted Form values and then rejects any method for which the form values don't match (excluding the button name, of course).
Here's an example:- http://blog.abodit.com/2010/02/asp-net-mvc-ambiguous-match/
BUT, this isn't a good idea.