When creating a new API controller in a Web Application the template code created if you choose to include read/write actions provides a good overview of how to pass values through to the API methods and return results.

The template assumes that the controller only has one action per HTTP verb (GET, POST, PUT, DELETE) and so if you try to add in another action with a different name for a verb you may get an AmbiguousActionException AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied:. This can be seen in the below default code to which I’ve added a HelloWorld action for GET.

namespace ProductRatingApi.Controllers
{
    [Produces("application/json")]
    [Route("api/Values")]
    public class ValuesController : Controller
    {
        // GET: api/Values
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        [HttpGet]
        public string HelloWorld()
        {
            return "Hello World!";
        }

        // GET: api/Values/5
        [HttpGet("{id}", Name = "Get")]
        public string Get(int id)
        {
            return "value";
        }
        
        // POST: api/Values
        [HttpPost]
        public void Post([FromBody]string value)
        {
        }
        
        // PUT: api/Values/5
        [HttpPut("{id}")]
        public void Put(int id, [FromBody]string value)
        {
        }
        
        // DELETE: api/ApiWithActions/5
        [HttpDelete("{id}")]
        public void Delete(int id)
        {
        }
    }
}

In this case, going to api/values produces an AmbiguousActionException error and api/values/helloworld maps to Get(int id) as the routing treats the action name helloworld as the id parameter. Removing the Get(int id) action results in a method not found exception. To map to these actions correctly we need to update the controller routing template to take account of controller name and action name like so.

[Route("api/[controller]/[action]")]

Action names now need to be stated explicitly in the URL but this means it’s possible to have more than one named action for a HTTP verb.


0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *