钱行慕

导航

【译】ASP.NET Core Web APIs(二):使用ASP.NET Core创建Web APIs 【中篇】

原文链接:传送门

特性路由需求

[ApiConroller]特性使得特性路由成为一个需求。举个例子:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

通过由 Startup.Configure中的UseEndpointsUseMvc,或者r UseMvcWithDefaultRoute方法定义的常规路由是不能访问Action方法的。

自动HTTP 400 响应

[ApiController] 特性使得模型验证错误自动触发一个HTTP 400 响应。因此,在一个Action方法中,如下代码是不必要的:

if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

ASP.NET Core MVC使用ModelStateInvalidFilter 这个动作过滤器来进行上述检查。

默认的BadRequest响应

使用兼容性版本2.1,对于一个HTTP 400响应的默认响应类型是SerializableError。如下的请求体是一个序列化类型的示例:

{
  "": [
    "A non-empty request body is required."
  ]
}

使用兼容性版本2.2及以后,那么对于一个HTTP 400响应,默认的响应类型是 ValidationProblemDetails。如下的请求体是一个序列化类型的示例:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|7fb5e16a-4c8f23bbfc974667.",
  "errors": {
    "": [
      "A non-empty request body is required."
    ]
  }
}

这个ValidationProblemDetails 类型:

  • 对于在web API中指定错误,提供了一个机器可读的格式。
  • 使用 RFC 7807 specification 进行编译。

记录自动的HTTP 400 响应

请参考How to log automatic 400 responses on model validation errors (aspnet/AspNetCore.Docs #12157)

禁用自动的HTTP 400响应

为了禁用自动HTTP 400行为,可以将属性SuppressModelStateInvalidFilter设置为true。在Startup.ConfigureServices方法中添加如下高亮显示的代码:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

绑定源参数引用

一个绑定源特性定义了一个Action 参数的值被找到的位置。绑定源特性具有如下种类:

特性对应的绑定源
[FromBody] 请求体
[FromForm] 请求体中的表单数据
[FromHeader] 请求头
[FromQuery] 请求查询字符串参数
[FromRoute] 来自于当前请求的路由数据
[FromServices] 作为一个Action参数而注入的请求服务

原文链接:传送门

注意:当值可能包含%2f(也就是/)时,请不要使用[FromRouter],%2f不会被转义为 /。如果值可能包含%2f时,请使用[FromQuery]。

如果没有[ApiController] 特性或者像是[FromQuery]这样的绑定源特性,那么ASP.NET Core运行时会试图复杂对象模型绑定器。复杂对象模型绑定i会以定义好的顺序从值提供器中拉取数据。

在如下的示例中,[FromQuery]特性表名discontinuedOnly参数值从请求URL的查询字符串中获取其值:

[HttpGet]
public ActionResult<List<Product>> Get(
    [FromQuery] bool discontinuedOnly = false)
{
    List<Product> products = null;

    if (discontinuedOnly)
    {
        products = _productsInMemoryStore.Where(p => p.IsDiscontinued).ToList();
    }
    else
    {
        products = _productsInMemoryStore;
    }

    return products;
}

[ApiController]特性为Action参数的默认数据源应用推断规则。这些规则可以节省你的时间,使得你不必通过给Action参数应用绑定特性以手动的指定其绑定源。绑定源推断规则行为如下:

  • [FromBody]推断为复杂类型参数。一个[FromBody]推断规则的例外是具有一个特定意义(比如IFormCollection 或者CancellationToken.)的任何复杂类型,内置类型。绑定源推断代码将会忽略那些指定的类型。
  • [FromForm]被推断为类型为 IFormFile 和 IFormFileCollection的Action参数。其不会被推断为任何简单类型或者用户自定义类型。
  • [FromRouter]被推断为任何Action参数名称匹配于路由模板中的参数的情况。当超过一个的路由匹配到Action参数时,任何一个路由值都会被认为是[FromRouter]。
  • [FromQuery]被推断为任何其他的Action参数。

[FromBody]推断注意

[FromBody]不会被推断为任何简单类型,比如string 或者 int。因此,当确实需要那个功能的时候,[FromBody]特性需要被用于简单类型。

当一个Action具有多个方法参数是从请求体中进行绑定,则会抛出一个异常。举个例子,所有如下的Action方法前面会引起一个异常。

  • [FromBody]推断在两者上因为其都是复杂类型。
[HttpPost]
public IActionResult Action1(Product product, Order order)
  • 在一个参数上使用[FromBody],而另一个推断为[FromBody],因为其是复杂类型。
[HttpPost]
public IActionResult Action2(Product product, [FromBody] Order order)
  • 两者都有[FromBody]特性。
[HttpPost]
public IActionResult Action3([FromBody] Product product, [FromBody] Order order)

禁用推断规则

为了禁用绑定源推断,将 SuppressInferBindingSourcesForParameters 属性设置为true。在 Startup.ConfigureServices中添加如下代码:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Multipart/form-data 请求推断

当一个Action参数被 [FromForm] 特性标记时,[ApiController]特性会应用另一个推断规则。multipart/form-data请求content-type会被推断。

为了禁用默认的行为,在 Startup.ConfigureServices中将 SuppressConsumesConstraintForFormFileParameters属性设置为true:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

 

posted on 2020-05-25 20:49  钱行慕  阅读(654)  评论(0编辑  收藏  举报