Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asp.net Web Api routing not working

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."
}
like image 527
ataravati Avatar asked Feb 13 '14 17:02

ataravati


People also ask

What is ASP Net Web API routing?

Routing is how Web API matches a URI to an action. Web API 2 supports a new type of routing, called attribute routing. As the name implies, attribute routing uses attributes to define routes. Attribute routing gives you more control over the URIs in your web API.

How can I improve my Web API routing?

Routing inside Web API Just as you would route a controller inside ASP.NET MVC you can route API controllers in Web API applications, by adding custom routes to the route table. However instead of using the MapRoute method you should use the MapHttpRoute method.

What is the difference between MVC routing and Web API routing?

If you are familiar with ASP.NET MVC, Web API routing is very similar to MVC routing. The main difference is that Web API uses the HTTP verb, not the URI path, to select the action. You can also use MVC-style routing in Web API.

What is the default route template in Web API?

The default route template for the ASP.NET Web API application is “api/{controller}/{id}“. In this template, the term “api” is a literal path segment, and the {controller} and {id} are placeholder variables that will be replaced with the actual value.


2 Answers

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.

like image 140
Ananthan Unni Avatar answered Sep 19 '22 14:09

Ananthan Unni


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]

like image 26
Dalorzo Avatar answered Sep 19 '22 14:09

Dalorzo