Fixing Multiple actions were found that match the request Asp.net Web Api Error

WebApiTest Project Here

I’m currently developing a new project utilizing asp.net Web Api 4.5. I hit a frustrating issue today with regards to routing actions. The error is “Multiple actions were found that match the request” when I added a new method to my code bypassing the built in GET,POST,PUT convention that web API supports out of the box.

The default scaffold controller web api gives you has the following pattern out of the box.

    public class TestController : ApiController
    {
        // GET api/test
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
 
        // GET api/test/5
        public string Get(int id)
        {
            return "value";
        }
 
        // POST api/test
        public void Post([FromBody]string value)
        {
        }
 
        // PUT api/test/5
        public void Put(int id, [FromBody]string value)
        {
        }
 
        // DELETE api/test/5
        public void Delete(int id)
        {
        }
    }

Problems start to appear when you want to go beyond this convention such as another “GET” method that goes by a different name.

    public class TestController : ApiController
    {
        // GET api/test
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
 
        // GET api/test/GetAllWithFilter
        [HttpGet]
        public IEnumerable<string> GetAllWithFilter()
        {
            return new string[] { "value1"};
        }
 
        // GET api/test/5
        public string Get(int id)
        {
            return "value";
        }
 
        // POST api/test
        public void Post([FromBody]string value)
        {
        }
 
        // PUT api/test/5
        public void Put(int id, [FromBody]string value)
        {
        }
 
        // DELETE api/test/5
        public void Delete(int id)
        {
        }
    }

This shouldn’t be that hard to fix on the surface but the built in route that enables this convention actually makes this much more difficult that it should be. I searched around for a while to figure out how to solve this then finally ran across a great Stackoverflow post here that nails it. Sadly this post isn’t even marked as the answer, it should be.

In short replace your built in route in WebApiConfig with this (updated for latest release). Be sure to modify your api path to suit your application.

            config.Routes.MapHttpRoute("DefaultApiWithId", "api/v1/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = @"\d+" });
            config.Routes.MapHttpRoute("DefaultApiWithAction", "api/v1/{controller}/{action}");
            config.Routes.MapHttpRoute("DefaultApiGet", "api/v1/{controller}", new { action = "Get" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) });
            config.Routes.MapHttpRoute("DefaultApiPost", "api/v1/{controller}", new { action = "Post" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) });
            config.Routes.MapHttpRoute("DefaultApiPut", "api/v1/{controller}", new { action = "Put" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Put) });
            config.Routes.MapHttpRoute("DefaultApiDelete", "api/v1/{controller}", new { action = "Delete" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Delete) });

This honors the GET,POST,PUT,DELETE convention while allowing you to create differently named actions in the same controller!

Update – Sample Project

As requested here is a sample project that I have verified works.

WebApiTest Project Here

Be Sociable, Share!
Tagged: , , , ,

Discussion

  1. Dharmesh Tailor says:

    Thanks for the wondeful article, But there was one problem that I faced while implementing this. I was not able to call PUT, POST & DELETE action methods when I include the routes provided by you. I have to call them like controller/Put, controlle/Post, controller/Delete.

    SO the work around for the same is that we change the order of the routes, by putting Get, Put, Post and Delete routes above the other 2. And this worked for me.

    Here are my routes.

    config.Routes.MapHttpRoute(“DefaultApiGet”, “{controller}”, new { action = “Get” }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) });
    config.Routes.MapHttpRoute(“DefaultApiPost”, “{controller}”, new { action = “Post” }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) });
    config.Routes.MapHttpRoute(“DefaultApiPut”, “{controller}”, new { action = “Put” }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Put) });
    config.Routes.MapHttpRoute(“DefaultApiDelete”, “{controller}”, new { action = “Delete” }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Delete) });
    config.Routes.MapHttpRoute(“DefaultApiWithAction”, “{controller}/{action}”, new { action = “Get” });
    config.Routes.MapHttpRoute(“DefaultApi”, “{controller}/{id}”, new { id = RouteParameter.Optional });

    • LoneTechie says:

      Glad you got it to work, you might want to investigate Attribute Based Routing, a new feature that can simplify some of this.

  2. Anthony says:

    Great article!
    I have this problem aswell. I have a Aspx Webform app, that posts to a WebAPI app. This WebApi app makes a duplicate copy using HTTPClient.PostAsXml method in a location that only accepts XML. The form posts fine into the First MVC WebApi App. If I enable the second post this happens. Any ideas? Much obliged and appreciated.

    Anthony.

  3. Anthony says:

    When I made these changes I get the following error while posting from the WenForm now:

    No HTTP resource was found that matches the request URI ‘http://localhost:57222/api/customers’.

    No action was found on the controller ‘Customers’ that matches the name ‘Post’.

    </Error
    _____________________________________
    This was my old entry
    //config.Routes.MapHttpRoute(
    // name: "DefaultApi",
    // routeTemplate: "api/{controller}/{id}",
    // defaults: new { id = RouteParameter.Optional }

    ————————————————————
    Here are my new ones
    config.Routes.MapHttpRoute("DefaultApiWithId", "api/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = @"\d+" });
    config.Routes.MapHttpRoute("DefaultApiWithAction", "api/{controller}/{action}");
    config.Routes.MapHttpRoute("DefaultApiGet", "api/{controller}", new { action = "Get" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) });
    config.Routes.MapHttpRoute("DefaultApiPost", "api/{controller}", new { action = "Post" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) });
    config.Routes.MapHttpRoute("DefaultApiPut", "api/{controller}", new { action = "Put" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Put) });
    config.Routes.MapHttpRoute("DefaultApiDelete", "api/{controller}", new { action = "Delete" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Delete) });

    Please help!
    Regards,
    Anthony

  4. Anthony says:

    Sorry,
    Though I still get this error while posting the form, I get the listing if I highlight the Address bar and hit enter.

    • LoneTechie says:

      Hi Anthony, post your web api controller code or at least your definitions

    • LoneTechie says:

      I just added a sample project. It is very likely you need to decorate your extra post method with [HttpPost] The sample project has two get and two post methods that both work as they are supposed to.

  5. Anthony says:

    My test projects were using a List to add the new entries. After I used EF the error stopped. My VS 2012 just crashed so I am going to reboot my machine and give this a whirl. Thanks a bunch.

    Regards,
    Anthony

  6. Anthony says:

    I just want to say how glad I’m to have found your site! I love the articles and the appeal. I am going to be taking a sabbatical soon and I have a lot to catch up and I am going to soak up this site. BTW Wanted to get your opinion on servicestack.net..

    Regards,
    Anthony

  7. Phillip says:

    After having issues for more than a year with tricky route config issues on numerous project, I just implemented this. It works. That’s all I can say, it works perfectly.

    You just made my day, thanks for sharing.

    • Anthony says:

      @Phillip if it wasn’t for this site I’d have lost my head! Since this was written a while ago when no other options were available, why not use WebAPI 2 with Attribute Routing? Let me know if you need any help.

  8. RODRIGO CHIARATO DOMINGUES says:

    I received this error after implementation of method public.
    web api undestand that this post method , but not. wasnt it .

    then i put the private keyword in method. Resolved!!

    thanks

Add a Comment

*