Asp.net Web Api routing не работает

Вот моя конфигурация маршрутизации:

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

И вот мой контроллер:

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...
    }
}

Когда я пытаюсь api/Products/GetProducts/, он работает. api/Products/Product?name=test также работает, но api/Products/Product/test не работает. Что я делаю неправильно?

UPDATE:

Вот что я получаю, когда пытаюсь 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."
}

Ответ 1

Это связано с настройками маршрутизации и значениями по умолчанию. У вас есть два варианта.

1) Изменив настройки маршрута в соответствии с параметром Product() в соответствии с URI.

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

2) Другой и рекомендуемый способ - использовать правильный атрибут подписи метода.

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

Это связано с тем, что метод ожидает параметра id при запросе api/Products/Product/test вместо поиска параметра name.

Ответ 2

Исходя из вашего обновления:

Обратите внимание, что WebApi работает на основе отражения, это означает, что ваши фигурные скобки {vars} должны совпадать с тем же именем в ваших методах.

Поэтому для соответствия этому api/Products/Product/test на основе этого шаблона "api/{controller}/{action}/{id}" Ваш метод должен быть объявлен следующим образом:

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

Если параметр string name был заменен на string id.

Вот мой полный образец:

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

Я попытался использовать совершенно другой шаблон:

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

Но это сработало с моей стороны. Btw я дополнительно удалил [AcceptVerbs("Get")] и заменил их на [HttpGet]