Partially update model with WebAPI2

7

I'm starting to develop a REST API using ASP.NET WebAPI2.

In my controller , I'm using the PATCH method to apply partial changes to a model .

I have a method that looks this way

[HttpPatch]
[ResponseType(typeof(void))]
public IHttpActionResult EditarNome(int id, string novoNome)
{
    var cliente = _db.Clientes.Find(id);

    if (cliente == null)
    {
        return NotFound();
    }

    cliente.Nome = novoNome;

    _db.Entry(cliente).State = EntityState.Modified;
    _db.SaveChanges();

    return StatusCode(HttpStatusCode.NoContent);
}

This method takes a new name as parameter and updates the Nome property of the model.

At the time of the request, the endpoint is api/Clientes/1?novoNome=JoaquimAlbertoSilva

Following this logic, I would need to create three more methods, in order to give the client the option to edit only these 4 properties of the Client model.

My questions are:

  • Is this approach right? Should I just do one method?

  • Would it be better for me to define a route for each type of change? Something like:
    api/Clientes/1/EditarNome/{novoNome}
    api/Clientes/1/EditarApelido/{novoApelido}

asked by anonymous 12.02.2016 / 19:18

2 answers

10

With this approach you are under utilizing the power of PATCH. The main advantage of this verb is that the client can only send the attributes to be changed, and this can be done in the same resource . Creating a new route for each attribute means more code than necessary.

What you need to use is the type Delta<T> (you need to include a new NuGet package, Microsoft.AspNet.WebApi.OData). If you have an operation that receives a parameter of that type, it will contain only the parameters passed by the client, and you can call the Patch method, which applies such changes, as in the example below.

[HttpPatch]
[ResponseType(typeof(void))]
public IHttpActionResult EditarNome(int id, Delta<Cliente> alteracoes)
{
    var cliente = _db.Clientes.Find(id);

    if (cliente == null)
    {
        return NotFound();
    }

    alteracoes.Patch(cliente);
    _db.SaveChanges();

    return StatusCode(HttpStatusCode.NoContent);
}

With this method, the client can send PATCH requests to any part of the record to be changed. For example:

PATCH /api/Clientes/1
Content-Type: application/json
Outros-Headers: ...

{ "Nome": "Nome alterado" }

or also:

PATCH /api/Clientes/1
Content-Type: application/json
Outros-Headers: ...

{ "Apelido": "Novo apelido" }

And you do not need to have more than one method to perform the same function (update the object on the server).

    
12.02.2016 / 19:36
4
  

Is this approach right?

Yes, according to RFC 5789 support , which explains how and when to use PATCH .

  

Should I just do one method?

If the partial update only requires one method, yes. If you need other partial update types, you will need to do more methods or use the Delta<T> object ( as the @ carlosfigueira ).

  

Would it be better for me to define a route for each type of change?

Yes, I would say that is a most elegant approach. Leaving everything in one method is also an option, but can greatly increase complexity.

Important!

There is no half-patch. If you patch, be sure to use all the attributes passed to the method. Anything other than this is best to use PUT (if it is an update of the whole object) or POST .

    
12.02.2016 / 19:24