Question

Here is my routing configuration:

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

And, here is my controller:

public class ProductsController : ApiController
{
    [AcceptVerbs("Get")]
    public object GetProducts()
    {
       // return all products...
    }

    [AcceptVerbs("Get")]
    public object Product(string name)
    {
       // return the Product with the given name...
    }
}

When I try api/Products/GetProducts/, it works. api/Products/Product?name=test also works, but api/Products/Product/test does not work. What am I doing wrong?

UPDATE:

Here's what I get when I try api/Products/Product/test:

{
  "Message": "No HTTP resource was found that matches the request URI 'http://localhost:42676/api/Products/Product/test'.",
  "MessageDetail": "No action was found on the controller 'Products' that matches the request."
}
Was it helpful?

Solution

This is because of your routing settings and its default values. You have two choices.

1) By changing the route settings to match the Product() parameter to match the URI.

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

2) The other and recommended way is to use the correct method signature attribute.

public object Product([FromUri(Name = "id")]string name){
       // return the Product with the given name
}

This is because the method is expecting a parameter id when requesting api/Products/Product/test rather than looking for a name parameter.

OTHER TIPS

Based on your update:

Please note that WebApi works based on reflection this means that your curly braces {vars} must match the same name in your methods.

Therefore to match this api/Products/Product/test based on this template "api/{controller}/{action}/{id}" YOur method needs to be declare like this:

[ActionName("Product")]
[HttpGet]
public object Product(string id){
   return id;
}

Where the parameter string name was replaced by string id.

Here is my full sample:

public class ProductsController : ApiController
{
    [ActionName("GetProducts")]
    [HttpGet]
    public object GetProducts()
    {
        return "GetProducts";
    }
    [ActionName("Product")]
    [HttpGet]
    public object Product(string id)
    {
        return id;
    }
}

I tried using a totally different template:

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

But it worked fine on my end. Btw I additional removed [AcceptVerbs("Get")] and replaced them with [HttpGet]

Your route is defining id as the parameter yet your method expects a name parameter. I prefer attribute routing if you can, then define /api/products/product/{name} on the Product method.

http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top