Search code examples
asp.netasp.net-corehttp-put

Proper Syntax of HttpPut


I'm studying MicroSoft's Tutorial: Create a web API with ASP.NET Core MVC. It explains you step-by-step how to create a HttpGet / HttpPost / HttpPut etc and how to call them.

My problem is: I can't call the HttpPut

The demo project represents a database with Todo items.

The TodoController contains functions to create / get / update / delete a TodoItem.

The HttpGet and HttpPost work as expected. I have problems with updating an existing item using a HttpPut.

class TodoItem
{
    public long Id { get; set; }
    public string Name { get; set; }
    public bool IsComplete { get; set; }
}

class TodoController : ControllerBase
{
    // Get all Todo items
    [HttpGet]
    public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems() {...}
    // get Todo item by Id
    [HttpGet("{id}")]
    public async Task<ActionResult<TodoItem>> GetTodoItem(long id){...}

    // Create a Todo item and return it with filled Id:
    [HttpPost]
    public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todo) {...}

    // The followingmethod is never called:    
    [HttpPut("{id}")]
    public async Task<IActionResult> PutTodoItem(long id, TodoItem todo)
    {
        ... // breakpoint never hit
    }
}

For the test I use PostMan. With Postman I can HttpGet and HttpPost. For example HttpPost:

Post to: https://localhost:44305/api/todo

Raw JSON body:
{
    "name":"get up in the morning",
    "isComplete":true
}

As expected, the Todo item is added and returned with a filled Id:

{
    "id": 3,
    "name": "get up in the morning",
    "isComplete": true
}

It is also possible to HttpGet the Todo item with Id 3. The HttpPut does not work, the function isn't called at all:

PUT: https://localhost:44305/api/todo/3

Raw JSON body:
{
    "id": 3,
    "name": "changed1",
    "isComplete": false
}

Postman receives the following raw JSON data:

{
    "": [
        "The input was not valid."
        ]
}

The strange thing is, that if I change the method definition, the function is called with the same JSON input:

[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id)
{
    ... // breakpoint hit
}

Obviously I have nothing to update.

I think that the parameter in the HttpPutAttribute isn't correct. What should I change to get my put called?


Solution

  • Your PUT method should contain [FromBody] before the TodoItem param as follows:

    [HttpPut("{id}")]
    public async Task<IActionResult> PutTodoItem(long id, [FromBody] TodoItem todo)
    {
         ... // now the breakpoint is hit!
    }