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 09:54

There is only one public signature allowed for each controller method. If you try to overload it, it will compile, but you're getting the run-time error you've experienced.

If you're not willing to use different verbs (like the [HttpGet] and [HttpPost] attributes) to differentiate overloaded methods (which will work), or change the routing, then what remains is that you can either provide another method with a different name, or you can dispatch inside of the existing method. Here's how I did it:

I once came into a situation where I had to maintain backwards compatibility. The original method expected two parameters, but the new one had only one. Overloading the way I expected did not work because MVC didn't find the entry point any more.

To solve that, I did the following:

  1. Changed the 2 overloaded action methods from public to private
  2. Created one new public method which contained "just" 2 string parameters. That one acted as a dispatcher, i.e.:

    public ActionResult DoSomething(string param1, string param2)
    {
        if (string.IsNullOrEmpty(param2))
        {
            return DoSomething(ProductName: param1);
        }
        else
        {
            int oldId = int.Parse(param1);
            return DoSomething(OldParam: param1, OldId: oldId);
        }
    }
    
    
    private ActionResult DoSomething(string OldParam, int OldId)
    {
        // some code here
        return Json(result);
    }
    
    
    private ActionResult DoSomething(string ProductName)
    {
        // some code here
        return Json(result);
    }
    

Of course, this is a hack and should be refactored later. But for the time being, it worked for me.

You can also create a dispatcher like:

public ActionResult DoSomething(string action, string param1, string param2)
{
    switch (action)
    {
        case "update":
            return UpdateAction(param1, param2);
        case "remove":
            return DeleteAction(param1);
    }
}

You can see, that UpdateAction needs 2 parameters, while DeleteAction just needs one.

查看更多
琉璃瓶的回忆
3楼-- · 2018-12-31 09:57

You can use the attribute if you want your code to do overloading.

[ActionName("MyOverloadedName")]

But, you'll have to use a different action name for the same http method (as others have said). So it's just semantics at that point. Would you rather have the name in your code or your attribute?

Phil has an article related to this: http://haacked.com/archive/2008/08/29/how-a-method-becomes-an-action.aspx

查看更多
看风景的人
4楼-- · 2018-12-31 09:58

I needed an overload for:

public ActionResult Index(string i);
public ActionResult Index(int groupId, int itemId);

There were few enough arguments where I ended up doing this:

public ActionResult Index(string i, int? groupId, int? itemId)
{
    if (!string.IsNullOrWhitespace(i))
    {
        // parse i for the id
    }
    else if (groupId.HasValue && itemId.HasValue)
    {
        // use groupId and itemId for the id
    }
}

It's not a perfect solution, especially if you have a lot of arguments, but it works well for me.

查看更多
呛了眼睛熬了心
5楼-- · 2018-12-31 09:59

Yes. I've been able to do this by setting the HttpGet/HttpPost (or equivalent AcceptVerbs attribute) for each controller method to something distinct, i.e., HttpGet or HttpPost, but not both. That way it can tell based on the type of request which method to use.

[HttpGet]
public ActionResult Show()
{
   ...
}

[HttpPost]
public ActionResult Show( string userName )
{
   ...
}

One suggestion I have is that, for a case like this, would be to have a private implementation that both of your public Action methods rely on to avoid duplicating code.

查看更多
不再属于我。
6楼-- · 2018-12-31 10:03

I like this answer posted in another thread

This is mainly used if you inherit from another controller and want to override an acction from the base controller

ASP.NET MVC - Overriding an action with differing parameters

查看更多
何处买醉
7楼-- · 2018-12-31 10:03

If this is an attempt to use one GET action for several views that POST to several actions with different models, then try add a GET action for each POST action that redirects to the first GET to prevent 404 on refresh.

Long shot but common scenario.

查看更多
登录 后发表回答