I have a C# Entity Framework Web API 2 controller. Currently when an attempt is made via the POST method to create an object with the same text for the main text field, I return a 409 Conflict error as an StatusCode result to indicate the addition is considered a duplicate.
What I'd like to do is return the server side object that triggered the duplicate error too. So I need something akin to the Ok() method but a variant that returns a 409 Conflict error as the HTTP status code instead of an HTTP OK status code.
Is there such a thing? How can I do this? If I can make this work the client doesn't have to do a subsequent Get call to the server to get the existing object after receiving a 409 Conflict error.
Here's the current POST method:
public IHttpActionResult PostCanonical(Canonical canonical)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// Check for duplicate Canonical text for the same app name.
if (db.IsDuplicateCanonical(canonical.AppName, canonical.Text))
{
// It's a duplicate. Return an HTTP 409 Conflict error to let the client know.
return StatusCode(HttpStatusCode.Conflict);
}
db.CanonicalSentences.Add(canonical);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = canonical.ID }, canonical);
}
Conflicts are most likely to occur in response to a PUT request. For example, you may get a 409 response when uploading a file that is older than the existing one on the server, resulting in a version control conflict.
HTTP 409 error status: The HTTP 409 status code (Conflict) indicates that the request could not be processed because of conflict in the request, such as the requested resource is not in the expected state, or the result of processing the request would create a conflict within the resource.
You should return Content:
return Content(HttpStatusCode.Conflict, original);
Content
is method on the ApiController
class which will create a NegotiatedContentResult
with the provided HttpStatusCode
and content. There is no need to create your own extension method on the ApiController class like in the accepted answer.
Arrived here looking for help with ASP.NET Core HTTP 409 - this is related, just the newer approach to solving this same problem.
return Conflict(new { message = $"An existing record with the id '{id}' was already found."});
EDIT: This solution is for WebApi prior v5, please see this answer if you are using v5 or above.
You could return a NegotiatedContentResult<T>
that lets you specify the status code and an object to be put into the http message body.
Change your code to something like this:
public IHttpActionResult PostCanonical(Canonical canonical)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// Check for duplicate Canonical text for the same app name.
if (db.IsDuplicateCanonical(canonical.AppName, canonical.Text))
{
// It's a duplicate. Return an HTTP 409 Conflict error to let the client know.
var original = db.CanonicalSentences.First(c => c.ID == canonical.ID);
return new NegotiatedContentResult<T>(HttpStatusCode.Conflict, original, this);
}
db.CanonicalSentences.Add(canonical);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = canonical.ID }, canonical);
}
Or maybe wrap it an extension method like this:
public static class HttpActionResultExtensions {
public static IHttpActionResult StatusCodeWithContent<T>(this ApiController @this, HttpStatusCode statusCode, T content) {
return new NegotiatedContentResult<T>(statusCode, content, @this);
}
}
And then use the extension like this:
public IHttpActionResult PostCanonical(Canonical canonical)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// Check for duplicate Canonical text for the same app name.
if (db.IsDuplicateCanonical(canonical.AppName, canonical.Text))
{
// It's a duplicate. Return an HTTP 409 Conflict error to let the client know.
var original = db.CanonicalSentences.First(c => c.ID == canonical.ID);
return StatusCodeWithContent(HttpStatusCode.Conflict, original)
}
db.CanonicalSentences.Add(canonical);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = canonical.ID }, canonical);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With