Update model partially with Webapi2

Asked

Viewed 222 times

7

I am starting to develop a REST API using ASP.NET Webapi2.

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

I have a method that is 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 property Nome of the model.

When the request is made the endpoint is api/Clientes/1?novoNome=JoaquimAlbertoSilva

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

My doubts are:

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

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

2 answers

10


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

What you need to use is the type Delta<T> (you need to include a new package of Nuget, Microsoft.AspNet.Webapi.Odata). If you have an operation that takes a parameter of this type, it will contain only the parameters passed by the client, and you can call the method Patch, implementing 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 don’t need to have more than one method to perform the same function (update the object on the server).

  • 4

    Much show the Delta<T>. +1.

  • Incredible. I intend to test the Delta<T> yet. The problem is that I can’t open the client to edit the entire model. Using the Delta<T> the customer can send the whole object and make it be completely updated.

  • After thinking a little bit about it, I think this is actually a much more elegant solution. Thanks for the contribution!

4

This approach is right?

Yes, second support of RFC 5789, which explains how and when to use the PATCH.

I must do only one method?

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

It would be better if I set a route for each type of change?

Yes, I would say it’s a very elegant approach. Leaving everything in one method is also an option, but it can rise enormously to complexity.

Important!

There is no half patch. If you patch, make sure to use all attributes passed to the method. Anything other than that you’d better use PUT (if it is an update of the whole object) or POST.

  • You don’t need multiple routes - the Web API has a feature that only applies changes sent by the client. Duplicate code (via multiple routes) is not the best way to deal with this problem.

  • @It depends a lot on what he wants to do. The PATCH is just for minor changes. As I said, if there are many of them, the correct thing is to leave for the PUT or POST.

  • The semantics of PUT is to exchange the object on the server with the one sent by the client - ie, change all properties. Even if there are many properties to be changed, if the client will not send the complete object, so PUT is not appropriate. The POST should be used to create new features (objects / entries in the BD, etc.) but it is so used for other purposes that it is not possible to define a clear rule for it... But in this case (partial change of an object), the PATCH is the most suitable.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.