【问题标题】:Returning appropriate messages to the calling client向调用客户端返回适当的消息
【发布时间】:2019-10-22 19:54:32
【问题描述】:

这很相似,但我的问题不同:Return content with IHttpActionResult for non-OK response

考虑到问题不同,我要求一个更简洁的答案,如果存在的话。

我的架构如下:

  1. Javascript/jQuery 调用后端控制器
  2. 后端控制器调用 WebAPI 服务
  3. WebAPI 服务查询 db(等)并返回数据

我有以下简化代码(Web API)...

示例 1 如果产品 ID 不存在则返回错误:

public IHttpActionResult GetProduct(int id)
{
    var product = products.FirstOrDefault((p) => p.Id == id);
    if (product == null)
    {
        return NotFound();
    }
    return Ok(product);
}

示例 2 如果产品 id 不存在则返回空数据:

public IHttpActionResult GetProduct(int id)
{
    var product = products.FirstOrDefault((p) => p.Id == id);
    return Ok(product);
}

客户端JS:

$.getJSON("example.json", function() {
  alert("success");
})
.done(function() { alert('Product retrieved'); })
.fail(function() { alert('Product doesn't exist. '); })
.always(function() { ... });

我已经读过很多次了,使用异常来控制流是不好的做法,这实际上是如果我使用NotFound() 会发生什么,因为它会命中.fail 函数,这表明存在错误(没有)。

在另一种情况下,评论必须由插入评论的人以外的人批准:

public IHttpActionResult ApproveComment(int rowId, string userName)
{
    try {
        return Ok(BusinessLogicLayer.ApproveComment(rowId, userName));
    }
    catch(Exception ex)
    { 
        // elmah.logerr...
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.InnerException == null ? ex.Message : ex.InnerException.Message));
    }
}

BusinessLogicLayer:
public string ApproveComment(int rowId, string userName)
{
    if (userName == _repository.GetInsertedCommentUserName()) {
        return "You cannot approve your own comment.";
    }
    if(_repository.ApproveComment(rowId, userName)){
        return "Comment approved";
    }
}

public string ApproveComment(int rowId, string userName)
{
    if (userName == _repository.GetInsertedCommentUserName()) {
        throw new Exception("You cannot approve your own comment.");
    }
    if(_repository.ApproveComment(rowId, userName)){
        return "Comment approved";
    }
}

在不使用异常的情况下,向用户返回适当消息的简洁优雅的方式是什么?

或者我的想法是错误的,从用户的角度来看是“特殊”情况吗? IE.,“当我传入这个 ID 时,我希望得到一个产品返回,但可惜它不存在!”从开发人员/测试人员的角度来看,我认为这不会是一个例外情况,但从最终用户的角度来看——也许吧。

【问题讨论】:

标签: c# rest asp.net-web-api error-handling controller


【解决方案1】:

您可以使用 HttpResponseMessage 自定义响应消息。它允许设置状态码、原因短语、消息和许多其他内容。

【讨论】:

    【解决方案2】:

    您在问两个不同的问题。所以让我们一一回答。

    “未找到”问题

    在第一种情况下,客户端尝试访问不存在的产品。从服务器返回的适当状态码是 404,未找到。对于客户端而言,这实际上是一个例外情况,因为它可能正在尝试访问现有资源。在客户端 JavaScript 的“失败”部分,您可以检查请求失败的原因(4xx 范围 = 客户端错误,5xx 范围 = 服务器端错误),并向用户显示适当的消息。

    “批准”问题

    对于批准问题,您返回了无用的状态代码。您应该在批准之前检查客户端尝试批准的资源是否存在。如果资源不存在,这是客户端错误,您应该返回 404,未找到。 如果业务逻辑层更新资源仍然失败,这是服务器问题,您应该返回 500,内部服务器错误。对于客户端错误导致更新失败的任何情况,返回 4xx 范围内的状态码。 (如403,未授权,如果不允许客户端批准自己的cmets)

    【讨论】:

    【解决方案3】:

    批准您自己的 cmets - 这似乎是一个无效操作。有一个例外。

    这是来自客户端的错误请求。有一个响应状态码。

    如果您按顺序处理异常,则代码中包含异常并没有错。如果您在客户端优雅地处理它们,那么给出 4xx 状态码也没有错。 这是一个不允许客户端提出的请求,所以它应该失败,不是吗?

    您的第二个示例与第一个示例不同。在第二个示例中,您肯定将无法实现某些目标。这是一个错误的请求

    第一个例子,嗯,你尝试实现默认情况下不禁止的事情 - 获取具有给定 id 的记录。而且恰好是这个记录不存在的情况。这是您的项目未找到的情况。

    【讨论】:

      猜你喜欢
      • 2021-07-19
      • 1970-01-01
      • 2013-03-17
      • 2016-12-02
      • 1970-01-01
      • 1970-01-01
      • 2020-07-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多