4

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

2
  • Hmm, it shouldn't be possible for those route to match Active action unless you apply HttpGet attribute on it. Commented Jul 31, 2012 at 12:34
  • I have updated the question to add HttpGet attribute Commented Jul 31, 2012 at 15:01

1 Answer 1

6

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

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks you for your answer, and yes, I know the default routing framework does not support this basically, I am trying to find the ways to work around. Your assumption of course works perfectly. But I was thinking whether we can apply Route Constraint in here
But in your example, both actions map to "GET api/values". A route constraint determines whether a given URI matches the template. It either matches or doesn't. The action is selected only after the route matches. If both actions have the same parameter signature and same HTTP method, and you are not using action-based routing, then necessarily they are ambiguous.
Thanks Mike for your comment, I got your point, if we cannot use route constraint as your mention, is there any approach that we can avoid exception thrown out by choosing either specified action or the first action?
Then the next question is: What do you want your URIs to look like? If "api/values" should select the first action, what do you want for the URI of the other action? (I'm not really sure what you're trying to do...)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.