all! I am using OData v4 building REST services. My tables have a GUID primary key.
My GET and POST requests are working fine. But the PUT, PATCH, and DELETE requests fail with 404.
I am not sure what the url should look like. I've tried these in Fiddler, all getting the 404. I have googled this quite a bit with no luck.
http://localhost/ershubrest/AppVersions/guid'00000000-e90f-4938-b8f6-000000000000'
http://localhost/ershubrest/AppVersions/'00000000-e90f-4938-b8f6-000000000000'
http://localhost/ershubrest/AppVersions/00000000-e90f-4938-b8f6-000000000000
Here is the code for my controller...
using ERSHubRest.Models;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.OData;
using System.Web.OData.Query;
using System.Web.OData.Routing;
namespace ERSHubRest.controllers
{
[ODataRoutePrefix("AppVersions")]
public class AppVersionsController : ODataController
{
HubModel db = new HubModel();
private bool AppVersionsExists(System.Guid key)
{
return db.AppVersions.Any(p => p.AppVersionId == key);
}
// http GET for select queries
[ODataRoute]
[EnableQuery]
public IQueryable<AppVersions> Get()
{
return db.AppVersions;
}
[ODataRoute("({key})")]
[EnableQuery]
public IHttpActionResult Get([FromODataUri] System.Guid key)
{
IQueryable<AppVersions> result = db.AppVersions.Where(p => p.BusinessId == key);
if (result == null)
{
return NotFound();
}
return Ok(result);
}
// http POST for insert
[ODataRoute()]
[HttpPost]
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
public async Task<IHttpActionResult> Post(AppVersions appVersions)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.AppVersions.Add(appVersions);
await db.SaveChangesAsync();
return Created(appVersions);
}
// http PUT and PATCH for updates
[ODataRoute()]
[HttpPatch]
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
public async Task<IHttpActionResult> Patch([FromODataUri] System.Guid key, Delta<AppVersions> appVersions)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var entity = await db.AppVersions.FindAsync(key);
if (entity == null)
{
return NotFound();
}
appVersions.Patch(entity);
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!AppVersionsExists(key) )
{
return NotFound();
}
else
{
throw;
}
}
return Updated(entity);
}
[ODataRoute()]
[HttpPut]
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
public async Task<IHttpActionResult> Put([FromODataUri] System.Guid key, AppVersions update)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if ( ! key.Equals( update.BusinessId ))
{
return BadRequest();
}
if (!AppVersionsExists(key))
{
return BadRequest();
}
db.Entry(update).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if ( ! AppVersionsExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(update);
}
// last is Delete
[ODataRoute()]
[HttpDelete]
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
public async Task<IHttpActionResult> Delete([FromODataUri] System.Guid key)
{
var appVersions = await db.AppVersions.FindAsync(key);
if (appVersions == null)
{
return NotFound();
}
db.AppVersions.Remove(appVersions);
await db.SaveChangesAsync();
return StatusCode(HttpStatusCode.NoContent);
}
// clean up
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
The request URL for PATCH, PUT and DELETE should be:
http://localhost/ershubrest/AppVersions(00000000-e90f-4938-b8f6-000000000000)
OData is using parenthesizes for addressing single entities using keys.
For more URL conventions, the OData V4 URL convention spec can be referred to: http://docs.oasis-open.org/odata/odata/v4.0/os/part2-url-conventions/odata-v4.0-os-part2-url-conventions.html