I have a very simple MVC5 WebApi project with the following models:
public class Product
{
public Product()
{
}
public int ProductId { get; set; }
public string ProductCode { get; set; }
public int BomId { get; set; }
public virtual BOM BOM { get; set; }
}
public class BOM
{
public BOM()
{
Products = new List<Product>();
}
public int BomId { get; set; }
public string Description { get; set; }
public int Counter { get; set; }
public virtual List<Product> Products { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<BOM> BOMs { get; set; }
}
Here is the PUT action (the scaffolded action):
public IHttpActionResult PutProduct(int id, Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != product.ProductId)
{
return BadRequest();
}
db.Entry(product).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!ProductExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
When the code executes db.SaveChanges(); the code executes as expected but the database doesn't get updated.
Here is the code in the console application that triggers the PUT request:
static async Task UpdateProduct(int Id)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost.fiddler:49195/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// New code:
HttpResponseMessage response = await client.GetAsync("api/products/" + Id.ToString());
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
Product product = JsonConvert.DeserializeObject<Product>(json);
product.BOM.Counter += 1;
json = JsonConvert.SerializeObject(product);
var httpContent = new StringContent(json, Encoding.UTF8, "application/json");
response = await client.PutAsync("api/products/" + Id.ToString(), httpContent);
Console.WriteLine(response.IsSuccessStatusCode.ToString() + ": Counter = " + product.BOM.Counter);
}
}
}
What this method does is get the product requested (1), updates a field in the child (BOM.Counter) by incrementing a value on that field.
It's just that the database does not update so when the application starts again, obviously we're getting the old value and not the updated one. The SaveChanges method seems to execute but the database doesn't suggest that it has.
Here are the get and put json strings from the PUT method as per Fiddler2:
Note: I have these lines of code in my Global.asax file so that Json handles the models correctly:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
I'm hoping someone can see where I'm going wrong. Any help would really be appreciated.
Thanks in advance,
Paul.