Tengo un controlador C# Entity Framework Web API 2 . Actualmente, cuando se realiza un intento a través del método POST para crear un objeto con el mismo texto para el campo de texto principal, devuelvo un error de conflicto 409 como resultado de StatusCode para indicar que la adición se considera un duplicado.
Lo que me gustaría hacer es devolver el objeto del lado del servidor que también provocó el error duplicado. Así que necesito algo parecido al método Ok() pero una variante que devuelva un error de conflicto 409 como código de estado HTTP en lugar de un código de estado HTTP OK .
¿Existe tal cosa? ¿Cómo puedo hacer esto? Si puedo hacer que esto funcione, el cliente no tiene que hacer una llamada Get posterior al servidor para obtener el objeto existente después de recibir un error de conflicto 409.
Aquí está el método POST actual:
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); }Debes devolver Contenido:
return Content(HttpStatusCode.Conflict, original); Content es un método en la clase ApiController que creará un NegotiatedContentResult con el HttpStatusCode y el contenido proporcionados. No es necesario crear su propio método de extensión en la clase ApiController como en la respuesta aceptada.
Llegué aquí en busca de ayuda con ASP.NET Core HTTP 409: esto está relacionado, solo el enfoque más nuevo para resolver este mismo problema.
return Conflict(new { message = $"An existing record with the id '{id}' was already found."});EDITAR: esta solución es para WebApi anterior a v5, consulte esta respuesta si está utilizando v5 o superior.
Podría devolver un NegotiatedContentResult<T> que le permita especificar el código de estado y un objeto que se colocará en el cuerpo del mensaje http.
Cambia tu código a algo como esto:
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); }O tal vez envuélvalo en un método de extensión como este:
public static class HttpActionResultExtensions { public static IHttpActionResult StatusCodeWithContent<T>(this ApiController @this, HttpStatusCode statusCode, T content) { return new NegotiatedContentResult<T>(statusCode, content, @this); } }Y luego usa la extensión así:
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); }