Question

This question could have been answered hundred times, but I couldnt find a proper resource. In a WebApi project (default project provided by VS) I have the ValuesController as below.

   public string Get(int id)
    {
        return "value";
    }

    [HttpGet]
    public string FindByName(string name)
    {
        return name;
    }

    [HttpGet]
    public string FindById(int id)
    {
        return id.ToString();
    }

In the WebApiConfig.cs, I have following route mapping.

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


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

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

Now only the FindById() action is working when i try in the browser. Why does the rest of api calls return "No HTTP resource was found that matches the request"

How can I get all three methods working? without using AttributeRouting. Am I lack of basic concepts of web api? ( i think yes)

Was it helpful?

Solution 3

Your actionApiById Route also matches the actionApi route, As your id is integer try using constraint like this.

config.Routes.MapHttpRoute(
              name: "actionApiById",
              routeTemplate: "api/{controller}/{action}/{Id}",
              defaults: new { action = "FindById", Id = RouteParameter.Optional }
              constraints: new {Id = @"\d+" }
              );

OTHER TIPS

AS We all know REST is resource based and this identify the resource with the URL, so that not more than one method with same parameter will be allowed in the REST service but there is work around in MVC 5 Web Api method level routing.

Here is the example you can do that:

[HttpGet]
[Route("api/search/FindByName/{name}")]
FindByName(string name)
{
}

[HttpGet]
[Route("api/search/FindById/{name}")]
FindById(int searchId)

Note:"search" is the controller name.

Please let know if need more clarification.

In general you don't want to have a route per action like your sample suggests. As your app grows this will get quickly out of hand.

Also consider building your url space in a way that will look just RESTfull

So methods will be GetById, GetByName, and then pass the parameters in the query string to match the right action (BTW not sure what the difference in your case is between GetById and FindById if they are not really different consider just keeping one of them around).

You can stick with the default route and your request will look like:

/api/controller/345 or /api/controller?name=UserName or /api/controller?SearchId=345 (assuming search was indeed a different behavior)

Then the method signatures:

Get(int id)
{
}

[HttpGet]
FindByName(string name)
{
}

[HttpGet]
FindById(int searchId)
{
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top