asp.net-web-apihttp-posthttp-getfrombodyattribute

MVC Api Controller Method HttpPost not working


I am using Visual Studio 2013...

I am having some problems with Api Controller Method.

I understand the differences between HTTPGET, HTTPPUT, [FromUri] and [FromBody].

I have a simple Method, and I am testing all combination.

When I run

http://localhost:62536/api/Controller/Method/10

I Got HTTP 404 error is this examples

[HttpPut]
public string Method([FromUri] int a)
{
return "";
}

[HttpPut]
public string Method( int a)
{
return "";
}

[HttpGet]
public string Method([FromUri] int a)
{
return "";
}

[HttpGet]
public string Method( int a)
{
return "";
}

Got HTTP 405 error is this examples

 [HttpPut]
         public string Method([FromBody] int a)
         {
         }

NO Error, but parameter a is 0..

 [HttpGet]
         public string Method([FromBody] int a)
         {
             return a.ToString();
         }

In other words.. It does not work using [HttpPut] or using parameter not defined or defined as [FromUri].

It only Works with [HttpGet] and [FromBody], but parameters is null.

My WebApiConfig look like this

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

Why it is not working?


Solution

  • You have to name your parameter in the controller methods as they are named in the route configuration. So, either name it as id:

    [HttpPut]
    public string Method(int id)
    {
    return "";
    }
    
    [HttpGet]
    public string Method(int id)
    {
    return "";
    }
    

    ...or, change it in the route config:

     public static void Register(HttpConfiguration config)
     {
         config.Routes.MapHttpRoute(
             name: "DefaultApi",
             routeTemplate: "api/{controller}/{action}/{a}",
             defaults: new { a = RouteParameter.Optional }
         );
    
     }
    

    Notice that it is now configured as a instead of id

    Update

    Here are controller methods that should work for the route configured as above:

    // Example URI: http://localhost:62536/api/Controller/PutMethod/10
    [HttpPut]
    public string PutMethod(int a)
    {
    return a.ToString();
    }
    
    // Example URI: http://localhost:62536/api/Controller/GetMethod/10
    [HttpGet]
    public string GetMethod(int a)
    {
    return a.ToString();
    }
    
    // Example URI: http://localhost:62536/api/Controller/PutMethod/
    [HttpPut]
    public string PutMethod()
    {
    return "(none)";
    }
    
    // Example URI: http://localhost:62536/api/Controller/GetMethod/
    [HttpGet]
    public string GetMethod()
    {
    return "(none)";
    }
    

    Usage of GET, PUT, POST, DELETE HTTP Verbs

    In essence, RESTful API design revolves around resources which model a business/application domain, URIs that address them, and four basic operations GET, PUT, POST, DELETE (and sometimes the 5th, PATCH). For example, in a Human Resource application domain we have employees. We could represent a collection of employees as a resource addressed by the URI http://example.com/api/Employees and each single employee in the collection as a resource addressed by the URI http://example.com/api/Employee/id, where the id is the ID of an employee. So, we could have:

    If the route is configured like:

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

    The controller for employees could then be:

    public class EmployeesController : ApiController
    {
        // GET api/Employees
        public IEnumerable<Employee> Get()
        {
            List<Employee> employees = null;
            // Get here the list of employees
            return employees;
        }
    
        // POST api/Employees
        public int Post(Employee employee)
        {
            // Persist here the new employee and determine its ID (for example, identity in SQL Server)
            return employee.Id;  // Returns the ID of the newly created employee
        }
    
        // GET api/Employees/5
        public Employee Get(int id)
        {
            Employee employee;
            // Get here the employee with the id
            return employee;
        }
    
        // PUT api/Employees/5
        public Employee Put(int id, Employee employee)
        {
            var updatedEmployee;
            // Find existing employee with the id, update it with the data passed via employee argument and persist it
            return updatedEmployee;  // It's a good practice to return the updated entity back, especially in the case when updating changes some properties, e.g. summarized values, counts, etc.
        }
    
        // DELETE api/Employees/5
        // More complicated example showing communicating statuses back to the client regarding successfulness of the operation
        public IHttpAction Delete(int id)
        {
            Employee employee;
            // Find the employee with the id
            if (employee == null)
                return NotFound();  // The employee is not found. Signal 404, i.e. there's no resource at this URI.
            // Delete here the employee from the persistence mechanism
            return Ok();  // The employee is found and deleted. Signal 200 - OK
        }
    }
    

    Notice there's no need for attributes [HttpGet], [HttpPut], etc. It just all works by convention.

    Of course, it's an oversimplified example just to convey the point.

    Hope it helps.