提前了解 REST





5.00/5 (6投票s)
在客户端,我希望在登录失败时获取并显示适当的消息(例如:电子邮件或密码不正确)。如何用 REST 实现?
在哪里可以找到 REST 的基础知识?
有关 REST 的基础知识,请访问
在客户端,我希望在登录失败时获取并显示适当的消息(例如:电子邮件或密码不正确)。如何用 REST 实现?
请将此方法添加到 UsersController 中,如下所示:
[HttpPost] [Route("login")] [ValidationActionFilter()] public IHttpActionResult Login(LoginRequest request) { /*Verify username and pwd and throw exception if invalid*/ throw new ValidationException("users.login.invalidUserNameOrPwd"); }
在此代码中,我们强制 API 始终向客户端返回“users.login.invalidUserNameOrPwd”验证错误。
当调用“<root api>/users/login”时
响应如下:
我期望收到明确的错误消息(例如:电子邮件或密码不正确),但 API 返回“users.login.invalidUserNameOrPwd”作为异常的键。你可能误解了我的意思,对吗?
不,我理解你的期望。
在这种情况下,我们应该避免向最终用户发送明确的错误消息,因为 API 可以服务于多种类型的设备和多种语言。
因此,API 返回键,客户端将在其设备上以适当的语言将该键翻译成适当的消息。这让 API 专注于应用程序的业务,而不是花费时间将消息键翻译成当前用户的适当语言。
网上有人说,登录失败时应该使用 401(未授权)。在这种情况下,我们应该使用它吗?
不,不应该。
好的,那么,在这种情况下我应该使用哪个错误代码(HTTP 状态码)?
我明白了。上面 Login 函数的“ValidationActionFilter”有什么作用?
这是 .NET 中的一个属性。仔细查看“ValidationActionFilter”属性的代码,我们有
public class ValidationActionFilter : ActionFilterAttribute { public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { if (actionExecutedContext.Exception == null) { return; } if (actionExecutedContext.Exception is ValidationException) { actionExecutedContext.Response = actionExecutedContext.Request .CreateResponse(HttpStatusCode.BadRequest, ((ValidationException)actionExecutedContext.Exception).Errors); } } }
在此代码中,我们重写了“OnActionExecuted”方法。该方法将在函数执行后被调用。
在该函数中,我们检查适当函数的执行结果是否抛出任何 ValidationException 异常(使用 actionExecutedContext.Exception is ValidationException)。然后创建适当的响应并以 Bad Request (400) 返回给调用者/客户端。
我认为我们可以在 Login 函数中进行 try/catch 并按预期处理异常情况。
是的,我们可以。但是 try/catch 块会在所有函数中重复。这不好。
应用程序中通常有多少种错误/异常?
在我看来,通常有两种类型:
系统错误/异常
应用程序错误/异常。
我们通常以不同的方式处理这些类型的错误/异常。
你能详细解释一下系统错误吗?
它们是与网络、基础设施等相关的错误。
这意味着在这种情况下,调用者的请求还没有到达你的应用程序。例如:Not Found (404),.....
对于这些情况,我们可以显示错误页面或向用户显示错误消息。这对所有情况都一样。
那么,应用程序错误又如何呢?
从不同的角度来看,这与应用程序的逻辑有关。当调用者发送带有对适当逻辑无效的数据的请求到服务器时。例如:使用空的电子邮件/用户名登录。
在这种情况下,我们需要让调用者知道这些错误,并且它可以在登录表单上显示适当的错误。大多数验证错误都是应用程序错误/异常。
为了更清楚,你能给我一个用户登录系统时这两种错误的例子吗?
当然,让我们看看,用户在登录表单中输入他们的电子邮件/密码,并将请求发送到服务器,URI 为“<api root>/users/login”。
如果该 URI(“<api root>/users/login”)在服务器上不存在。这意味着服务器端未配置为处理此类型的请求。因此,.Net Framework 无法将你的请求映射到服务器上的适当操作。此错误是系统错误,因为在这种情况下你的应用程序代码未被执行。
否则,URI 存在并且调用了 UsersController 的 Login 方法。然后我们验证请求,发现电子邮件为空,但在此情况下是必需的。然后抛出异常。
在这种情况下,这是应用程序错误,因为该错误是由应用程序因数据不满足要求而抛出的。
调用者如何知道他们在调用我的 API 时收到了系统错误?
对于这些系统错误,服务器通常会响应特定的 HTTP 状态(例如:404:Not Found,...)。因此,调用者可以根据此来了解他们收到了哪种类型的错误。
应用程序错误/异常怎么样?
对于应用程序错误,我们应该返回带有 BadRequest (400) 的响应,并在响应正文中附加更多错误详细信息,如下图所示。
以及响应正文
好的,你能给我展示一下如何在 Web API 中实现这个吗?
请看下面的简单代码:
public HttpResponseMessage Login(LoginRequest request) { try { /*Verify username and pwd and throw exception if invalid*/ throw new ValidationException("users.login.invalidUserNameOrPwd"); } catch (ValidationException ex) { return Request.CreateResponse(HttpStatusCode.BadRequest, ex.Errors); } }
我注意到在失败/成功的情况下,错误/数据返回的方式不同。这要求客户端在处理来自服务器的响应之前进行仔细检查。有没有其他解决方案?
这是大多数 REST API 的常见问题。
为了避免这种情况,我们需要包装响应结果。这样,失败/成功两种情况下的响应格式将是相同的。
看下面的代码:
[HttpPost] [Route("login")] public HttpResponseMessage Login(LoginRequest request) { ResponseData<bool> response = new ResponseData<bool>(); try { /*Assume that we will throw exception in the case client send request ="exception"*/ if (request != null && request.Email == "exception") { throw new ValidationException("users.login.invalidUserNameOrPwd"); } else { response.SetData(true); } } catch (ValidationException ex) { response.SetError(ex.Errors); } return Request.CreateResponse(response.HasError() ? HttpStatusCode.OK : HttpStatusCode.BadGateway, response); }
在此代码中,我们始终向客户端返回 ResponseData 对象,它是 JSON 格式,我们知道它有多少个字段。
在成功的情况下,响应数据中的 errors 字段为 null/empty,因此我们可以从“data”字段获取数据并执行适当的操作,如下所示。
否则,在失败的情况下,只需获取“errors”字段中的错误列表并通知最终用户。
我们如何区分系统错误和应用程序错误?
我们可以基于“HTTP 状态码”来做到这一点。
在调用服务器时发生异常/错误的情况下,检查响应中是否有“errors”字段。
- 如果有,则是应用程序错误。只需从“errors”字段获取错误列表并执行适当的操作。
- 如果没有,这是系统错误。
我明白了,我们在每个函数中都有 try/catch 块来处理异常情况。正如本文所述,我们可以通过使用“ValidationActionFilter”来移除它,对吗?
是的,这是正确的。
感谢阅读。 CodeProject