How to bypass the exception multiple actions were

2019-05-04 10:54发布

问题:

When trying to find solution for this below question:

MVC Web Api Route with default action not working

Mostly I run across the problem "multiple actions were found". If routing mechanism finds out more than one actions matched with a route, it throws out the exception 500.

For example, there are two actions in ValuesController:

[HttpGet]
public IEnumerable<String> Active()
{
    var result = new List<string> { "active1", "active2" };
    return result;
}

public IEnumerable<string> Get()
{
    return new[] { "value1", "value2" };
}

which match with default route:

 routes.MapHttpRoute(
          name: "DefaultApi",
          routeTemplate: "api/{controller}/{id}",
          defaults: new { id = RouteParameter.Optional }
      );

With

GET: /api/values 

will get error multiple actions were found.

My question: how I can bypass the exception "multiple actions were found" by choosing specified action (choose the first matched action is also okay).

Update 1: Update from tugberk's comment, thanks to point out.

Update 2: Update from Mike's comment, seems the question is not correct much, so I change the way to ask by not mentioning the routing constraint.

Thanks

回答1:

First of all, it shouldn't be possible for those route to match Active action unless you apply HttpGet attribute on it. I will assume you already did that. The second thing is that what you want is not logical. You would like to make a get request and have two identical actions. You are now using so-called HTTP-method-based routing. For you situation, I am sure that so-called action-based routing is the best.

Assuming you have following two actions:

[HttpGet]
public IEnumerable<String> Active()
{
    var result = new List<string> { "active1", "active2" };
    return result;
}

[HttpGet]
public IEnumerable<string> Retrieve()
{
    return new[] { "value1", "value2" };
}

You route should be as follows:

routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );

Then you can request to those with following URIs:

GET /controllername/retrieve

GET /controllername/active