Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web API 2 does not process PATCH requests for Integers

I'm having a problem with Web API 2 (.net 4.5.1) in that it seems to ignore PATCH requests where the property is an integer, but processes other types without a problem (I've tested string and decimal).

I’ve setup an unsecured test API with a 'products' controller at http://playapi.azurewebsites.net/api/products. If you do a GET to that URL, you’ll get something like this product back:

{"Id": 1,"Name": "Xbox One","Category": "gaming","Price": 300,"Stock": 5}

‘Name’ and ‘Category’ are both strings, ‘Price’ is a Decimal and ‘Stock’ is an Integer.

If you send these requests, they both work (You’ll get a 200/OK with the updated entity):

  • PATCH, http://playapi.azurewebsites.net/api/products/1 with {"Price": 600.00}
  • PATCH, http://playapi.azurewebsites.net/api/products/1 with {"Category": "Electronics"}

However, if you send this, it returns 200/OK, but does not make the update and the stock remains at the original value

  • PATCH, http://playapi.azurewebsites.net/api/products/1 with {"Stock": 4}

My controller code is fairly standard boiler plate code (from the scaffolded ODATA controller but moved into a standard API controller):

// PATCH: api/Products/5
[AcceptVerbs("PATCH", "MERGE")]
public async Task<IHttpActionResult> PatchOrder(int id, Delta<Product> patch)
{
    Validate(patch.GetEntity());
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    var item = await db.Products.FindAsync(id);
    if (item == null)
    {
        return NotFound();
    }
    patch.Patch(item);
    try
    {
        await db.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!ProductExists(id))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }
    return Ok(item);
}

My model for 'Product' is as follows:

namespace PlayAPI.Models
{
    public class Product
    {
        [Key]
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public double Price { get; set; }
        public int Stock { get; set; }
    }
}

When I debug the controller, I see that the ‘patch’ object has a _changedProperties collection which has no items in it when I do an integer request, but when I do any other kind of request it has the key that I changed.

Should web API support PATCH requests for integer properties? If so, do I need to do anything special on the server or client to make it work?

like image 616
Martin Kearn Avatar asked Mar 12 '15 11:03

Martin Kearn


1 Answers

As a quick fix, Change the int to an Int64 on PlayAPI.Models.Product.

public Int64 Stock { get; set; }

It's my understanding that The Delta object used to patch the existing object doesn’t use JSON.net to convert and is silently throwing an Invalid cast exception when it parses JSON and then compares to the existing object from your database. You can read more about the bug over here: http://aspnetwebstack.codeplex.com/workitem/777

like image 187
Martin Beeby Avatar answered Sep 23 '22 15:09

Martin Beeby