我有一个C#Entity Framework Web API 2控制器。目前,当通过 POST 方法尝试创建主文本字段具有相同文本的对象时,我返回 409冲突错误作为 StatusCode 结果表明添加被视为重复。
我想做的是返回触发重复错误的服务器端对象。所以我需要一些类似于 Ok()方法的东西,但是一个返回 409 Conflict 错误的变体作为HTTP状态代码而不是HTTP OK状态代码< / em>的。
有这样的事吗?我怎样才能做到这一点?如果我可以完成这项工作,客户端在收到409冲突错误后,不必对服务器进行后续获取调用以获取现有对象。
这是当前的POST方法:
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);
}
答案 0 :(得分:17)
您应该返回内容:
return Content(HttpStatusCode.Conflict, original);
Content
是ApiController
类的方法,它将使用提供的NegotiatedContentResult
和内容创建HttpStatusCode
。无需像在接受的答案中那样在ApiController类上创建自己的扩展方法。
答案 1 :(得分:14)
编辑:此解决方案适用于v5之前的WebApi,如果您使用的是v5或更高版本,请参阅this answer。
您可以返回NegotiatedContentResult<T>
,它允许您指定状态代码和要放入http消息正文的对象。
将您的代码更改为以下内容:
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);
}
或者可以用这样的扩展方法包装它:
public static class HttpActionResultExtensions {
public static IHttpActionResult StatusCodeWithContent<T>(this ApiController @this, HttpStatusCode statusCode, T content) {
return new NegotiatedContentResult<T>(statusCode, content, @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);
}
答案 2 :(得分:1)
到达此处寻求ASP.NET Core HTTP 409的帮助-这与此相关,只是解决该问题的更新方法。
return Conflict(new { message = $"An existing record with the id '{id}' was already found."});
答案 3 :(得分:-1)
我遇到了与ASP.NET Core 1.0 RC2类似的问题,但我遇到了DbUpdateConcurrencyException
,使用了乐观并发,我不想让我的用户更新已经更新过的对象。
我还想将更新的对象返回给拨打电话的用户。我能够创建新的CreatedAtAction
并将StatusCode
设置为StatusCodes.Status409Conflict
context.Entry(user).State = EntityState.Modified;
try
{
await context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!UserExists(id))
{
return NotFound();
}
else
{
//remove the user we just added, otherwise it will not goto
//the database to obtain the updated user
context.Entry(user).State = EntityState.Detached;
var updatedUser = await context.Users.SingleOrDefaultAsync(m => m.Id == id);
if (updatedUser == null)
{
return NotFound();
}
var returnAction = CreatedAtAction("PutUser", new { id = user.Id }, updatedUser);
returnAction.StatusCode = StatusCodes.Status409Conflict;
return returnAction;
}
}