This is the Patch method of my OdataController
public async Task<IHttpActionResult> Patch([FromODataUri] int key, Delta<Product> patch)
{
Validate(patch.GetInstance());
Product product = await service.Products.GetAsync(key);
if (product == null)
return NotFound();
patch.Put(product);
try
{
await service.Products.UpdateAsync(product);
}
catch (DbUpdateConcurrencyException)
{
if (!await service.Products.ExistAsync(key))
return NotFound();
else
throw;
}
return Updated(product);
}
My model has a property:
[Timestamp]
public byte[] RowVersion { get; set; }
the DbUpdateConcurrencyExceptionseems not working at all.
I need to implement concurrency checking mechanism using Etag.
I have seen some examples here.But they are not using Delta in there method.
- How can I check Concurrency using etags?
- Is it possible to implement a custom attribute for concurrency cheacking?
Something Like:
[CustomConcurrencyCheck]
public async Task<IHttpActionResult> Put([FromODataUri] int key, Delta<Product> patch)
{
...
}
Providing a simple example will be highly appreciated.
First in
WebApiConfigwhile creating your model you have to specify which property is the ETag, in your case:Later you can retrieve the ETag from the
ODataQueryOptions<T>parameter of yourPatchmethod in the controller:This is the solution I use, it is a simple check to see if the client which requests the update has the same version of the object the service has. A notable drawback of my solution is that I have to retrieve the existing object from the DB to get it to work, that costs some performance.
This is code for the
If-Matchheader,ODataQueryOptions<T>also has.IfNoneMatch[VersionColumnName]available. Which you can use in yourGetmethod. If theIf-None-Matchheader equals yourRowVersionyou can return aHTTP 304 (Not modified)and save some bandwidth.This is a very simple example, if you want to implement your own custom attribute that's up to you. At the very least I would move some of this logic to a helper class so it can be reused.