Can you overload controller methods in ASP.NET MVC

2018-12-31 09:29发布

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 something that cannot be done?

The current request for action 'MyMethod' on controller type 'MyController' is ambiguous between the following action methods:

16条回答
人间绝色
2楼-- · 2018-12-31 10:04

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.

enter image description here

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.

enter image description here

enter image description here

The above answer i have taken from this codeproject article --> MVC Action overloading

查看更多
时光乱了年华
3楼-- · 2018-12-31 10:04

As far as I know you can only have the same method when using different http methods.

i.e.

[AcceptVerbs("GET")]
public ActionResult MyAction()
{

}

[AcceptVerbs("POST")]
public ActionResult MyAction(FormResult fm)
{

}
查看更多
浮光初槿花落
4楼-- · 2018-12-31 10:05

You could use a single ActionResult to deal with both Post and Get:

public ActionResult Example() {
   if (Request.HttpMethod.ToUpperInvariant() == "GET") {
    // GET
   }
   else if (Request.HttpMethod.ToUpperInvariant() == "POST") {
     // Post  
   }
}

Useful if your Get and Post methods have matching signatures.

查看更多
永恒的永恒
5楼-- · 2018-12-31 10:07

I have achieved this with the help of Attribute Routing in MVC5. Admittedly I am new to MVC coming from a decade of web development using WebForms, but the following has worked for me. Unlike the accepted answer this allows all the overloaded actions to be rendered by the same view file.

First enable Attribute Routing in App_Start/RouteConfig.cs.

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapMvcAttributeRoutes();

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );            
    }
}

Optionally decorate your controller class with a default route prefix.

[RoutePrefix("Returns")]
public class ReturnsController : BaseController
{
    //.......

Then decorate your controller actions that overload each other with a common route and parameters to suit. Using type constrained parameters you can use the same URI format with IDs of different types.

[HttpGet]
// Returns
public ActionResult Index()
{
    //.....
}

[HttpGet]
[Route("View")]
// Returns/View
public ActionResult View()
{
    // I wouldn't really do this but it proves the concept.
    int id = 7026;
    return View(id);
}

[HttpGet]
[Route("View/{id:int}")]
// Returns/View/7003
public ActionResult View(int id)
{
    //.....
}

[HttpGet]
[Route("View/{id:Guid}")]
// Returns/View/99300046-0ba4-47db-81bf-ba6e3ac3cf01
public ActionResult View(Guid id)
{
    //.....
}

Hope this helps and is not leading somebody down the wrong path. :-)

查看更多
登录 后发表回答