18

I have an ASP.NET Web API project with an ApiController that provides a User endpoint with the following actions:

GET /api/User
POST /api/User
DELETE /api/user

I want to provide the following endpoint:

GET /api/user/metrics

However, when I define the controller action like so:

[HttpGet]
public HttpResponseMessage Metrics()
{
    return null;
}

I get the Multiple actions were found that match the request error message.

I understand this violates the definition of a "pure" REST API but this is how I would like to do it. I imagine I have to solve this problem by mapping an HTTP route, but I have tried a few routes and I can't get it to work. What should my route look like?

2 Answers 2

19

The default route does not include the action.

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

It selects actions based on the controller, HTTP verb and the parameter, or lack of parameter, in the route. So, it is finding the correct controller and looking for a GET action with no parameter. It finds two.

You should add an additional route that includes the action. This is either done with attribute based routing as Kiran mentioned or by convention based routing. For convention based routing, the route is typically placed in the Application_start() method of WebApiConfig.cs. More specific routes go before general routes, so your routes would look something like this:

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

 config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
Sign up to request clarification or add additional context in comments.

4 Comments

I've configured exactly like this and got this error: {"Message":"No HTTP resource was found that matches the request URI 'http: //localhost:53873/api/ControllerName/4'.","MessageDetail":"No action was found on the controller 'ControllerName' that matches the name '4'."}
@Davi do you have the routes definitions in the correct order?
Yes, I have configured exactly like you described. If I configure in the oposite order then it says that multiple actions matches the route. The only route that is mapped before those is: config.Routes.MapODataRoute("OData", "odata", builder.GetEdmModel());. I don't think it would cause this conflict right?
It seems that this setup will do the required routing, but in the end I opted to keep the default route and declare real representative routes using Route and RoutePrefix attributes instead of action names ;]
17

If you are using Web API 2, I would suggest to use attribute routing which makes the experience easier for scenarios like these.

You can continue using the default conventional route for majority of your scenarios, but can use attribute routing in places where you are required to, like in your current scenario.

Following sample demonstrates a similar scenario:

http://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/WebApiAttributeRoutingSample/WebApiAttributeRoutingSample/Controllers/Api/CustomersController.cs

Comments

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.