Contract.Requires 用于网络验证 api
Contract.Requires for validations in web api
我正在开发基于 MVC5/Web API 的应用程序。在我读过的一些文章中,使用 Contract.Requires
(System.Diagnostics.Contracts
命名空间的一部分)来验证传入数据。
这是验证传入数据的正确方法吗?此外,我无法调试 Contract.Requires
行,因为调试器总是绕过这一行。我正在使用 Visual Studio 2013.
public async Task<UserInfo> Put(
[FromBody] UserInfo userInfo) {
Contract.Requires(userInfo != null);
..............
}
有人可以解释什么时候使用 Contract.Requires
以及在哪里避免使用吗?
您当然可以在控制器中使用代码契约,但这里有一些缺点和您可能不需要契约的原因。
API 响应中的错误详细信息丢失: 代码约定失败将作为 HTTP 500 内部服务器错误返回给客户端,可能没有详细信息,这对 API 的客户没有帮助。这是因为合约失败导致抛出异常。您可能更愿意用自己的详细信息抛出一个 HttpResponseException
,或者定制一个 HttpResponseMessage
。在那种情况下(除非您推出自己的全局异常处理)代码契约可能没有意义。
Contract.Requires 可能是多余的: 考虑 Web API 可能已经在验证您的参数。例如,缺少参数可能会导致路由无效,因此请求会被拒绝并且不会调用该方法。代码契约在这种方法中是无用的。
为什么需要合约?代码合约非常适合在编译时捕获合约失败。但除非您的 API 客户端也是 .NET 项目,否则您无法利用该功能。因此,请考虑您可能还需要合同做什么,以及是否证明它们的使用是合理的。
为什么要签约?
您可以在 api 方法中使用 HttpResponseMessage :
[HttpPost]
public HttpResponseMessage Put(UserInfo userInfo) {
if(ModelState.IsValid)
{
// your code
return Request.CreateResponse(HttpStatusCode.OK);
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest, new { msg = "invalid data" });
}
}
和或:
[HttpPost]
public async Task<ActionResult> Put(UserInfo userInfo) {
if(ModelState.IsValid)
{
// your code
return Request.CreateResponse(HttpStatusCode.OK);
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest, new { msg = "invalid data" });
}
}
虽然 Keith 在 Web.Api 中指出了使用代码契约的一些明显缺点,但我想分享一些关于它们可能有意义或派上用场的想法。
使用代码契约,您可以使用标准方法进行输入验证和参数验证(例如断言甚至 post 条件)。
这意味着您可以用相同的方式编码——无论您是在 ApiController 中还是在其他代码段(例如异步工作线程)中。
当然,发送给客户端的一般 HTTP 500 消息没有帮助,因此我们将代码契约与标准 Web.Api 异常处理程序 (HttpStatusExceptionFilterAttribute) 结合使用。此异常处理程序将检查消息并将自定义 HTTP 错误代码发送回客户端(可选地连同失败的条件),并且它可以将完整的堆栈跟踪记录到您的中央应用程序的日志工具中。
通过利用这两个功能,您可以清理和简化代码,同时向客户端提供友好且有意义的错误信息,并仍然保留完整的错误信息以供内部故障排除。
你可以看看这篇文章,对它进行了进一步的解释:Using CodeContracts with OData Controllers and Web.Api Exception Filters
希望这对您有所帮助
此致,罗纳德
我正在开发基于 MVC5/Web API 的应用程序。在我读过的一些文章中,使用 Contract.Requires
(System.Diagnostics.Contracts
命名空间的一部分)来验证传入数据。
这是验证传入数据的正确方法吗?此外,我无法调试 Contract.Requires
行,因为调试器总是绕过这一行。我正在使用 Visual Studio 2013.
public async Task<UserInfo> Put(
[FromBody] UserInfo userInfo) {
Contract.Requires(userInfo != null);
..............
}
有人可以解释什么时候使用 Contract.Requires
以及在哪里避免使用吗?
您当然可以在控制器中使用代码契约,但这里有一些缺点和您可能不需要契约的原因。
API 响应中的错误详细信息丢失: 代码约定失败将作为 HTTP 500 内部服务器错误返回给客户端,可能没有详细信息,这对 API 的客户没有帮助。这是因为合约失败导致抛出异常。您可能更愿意用自己的详细信息抛出一个
HttpResponseException
,或者定制一个HttpResponseMessage
。在那种情况下(除非您推出自己的全局异常处理)代码契约可能没有意义。Contract.Requires 可能是多余的: 考虑 Web API 可能已经在验证您的参数。例如,缺少参数可能会导致路由无效,因此请求会被拒绝并且不会调用该方法。代码契约在这种方法中是无用的。
为什么需要合约?代码合约非常适合在编译时捕获合约失败。但除非您的 API 客户端也是 .NET 项目,否则您无法利用该功能。因此,请考虑您可能还需要合同做什么,以及是否证明它们的使用是合理的。
为什么要签约?
您可以在 api 方法中使用 HttpResponseMessage :
[HttpPost]
public HttpResponseMessage Put(UserInfo userInfo) {
if(ModelState.IsValid)
{
// your code
return Request.CreateResponse(HttpStatusCode.OK);
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest, new { msg = "invalid data" });
}
}
和或:
[HttpPost]
public async Task<ActionResult> Put(UserInfo userInfo) {
if(ModelState.IsValid)
{
// your code
return Request.CreateResponse(HttpStatusCode.OK);
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest, new { msg = "invalid data" });
}
}
虽然 Keith 在 Web.Api 中指出了使用代码契约的一些明显缺点,但我想分享一些关于它们可能有意义或派上用场的想法。
使用代码契约,您可以使用标准方法进行输入验证和参数验证(例如断言甚至 post 条件)。 这意味着您可以用相同的方式编码——无论您是在 ApiController 中还是在其他代码段(例如异步工作线程)中。
当然,发送给客户端的一般 HTTP 500 消息没有帮助,因此我们将代码契约与标准 Web.Api 异常处理程序 (HttpStatusExceptionFilterAttribute) 结合使用。此异常处理程序将检查消息并将自定义 HTTP 错误代码发送回客户端(可选地连同失败的条件),并且它可以将完整的堆栈跟踪记录到您的中央应用程序的日志工具中。
通过利用这两个功能,您可以清理和简化代码,同时向客户端提供友好且有意义的错误信息,并仍然保留完整的错误信息以供内部故障排除。
你可以看看这篇文章,对它进行了进一步的解释:Using CodeContracts with OData Controllers and Web.Api Exception Filters
希望这对您有所帮助
此致,罗纳德