在实体框架支持的Web API 2 POST调用中返回一个对象和一个409冲突错误

本文关键字:一个对象 错误 冲突 一个 返回 支持 框架 实体 Web API 调用 | 更新日期: 2023-09-27 18:06:49

我有一个c#实体框架Web API 2控制器。目前,当尝试通过POST方法为主文本字段创建具有相同文本的对象时,我返回409冲突错误作为StatusCode结果,以表明添加被认为是重复的。

我想做的是返回触发重复错误的服务器端对象。因此,我需要类似于Ok()方法的东西,但返回409冲突错误作为HTTP状态码而不是HTTP Ok状态码的变体。

有这样的事吗?我该怎么做呢?如果我能使这个工作的客户端不需要做一个后续的Get调用到服务器得到一个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);
    }

在实体框架支持的Web API 2 POST调用中返回一个对象和一个409冲突错误

你应该返回Content:

return Content(HttpStatusCode.Conflict, original);

ContentApiController类上的方法,它将用提供的HttpStatusCode和内容创建一个NegotiatedContentResult。不需要在ApiController类上创建自己的扩展方法,就像在接受的答案中那样。

来这里寻求ASP的帮助。. NET Core HTTP 409 -这是相关的,只是解决相同问题的新方法。

冲突ActionResult

 return Conflict(new { message = $"An existing record with the id '{id}' was already found."});

编辑:此解决方案适用于WebApi v5之前的版本,如果您使用的是v5或更高版本,请参阅此答案。

你可以返回一个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);
}

我在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;                    
    }
}
相关文章: