【译】ASP.NET Core Web APIs,三:使用ASP.NET Core创建Web APIs 【下篇】

原文链接:传送门

Multipart/form-data 请求推断

当一个Action方法的参数被标记为[FromForm]特性时,[ApiController]特性会应用一个推断规则,此时,请求Content-Type被推断为 multipart/form-data。

为了禁用默认的行为,在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";
    });

错误状态代码的问题详细

当兼容性版本是2.2及以后,MVC会将一个错误结果(具有状态码400或者更改的结果)转化为一个带有 ProblemDetails的结果。ProblemDetails 是基于RFC 7807 specification,在一个HTTP响应中提供一个机器可读的错误详情。

考虑在一个控制器Action中的如下代码:

if (pet == null)
{
    return NotFound();
}

NotFound方法产生一个具有ProblemDetails体的错误代码。比如:

{
  type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
  title: "Not Found",
  status: 404,
  traceId: "0HLHLV31KRN83:00000001
}

禁用ProblemDetails响应

SuppressMapClientErrors 属性被设置为true时,就会禁用为错误状态代码自动创建ProblemDetails。在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";
    });

使用[Consumes]特性定义支持的请求上下文类型

默认情况下,一个Action支持所有可用的请求上下文类型。举个例子,如果一个app被配置为支持JSON和XML input formatters, 那么这个Action便支持多种上下文类型,包括 application/jsonapplication/xml。

[Cosumes]特性允许一个Action限制其支持的请求上下文类型。将[Cosume]应用到一个Action或者Controller上,指定一个或者多个上下文类型。

[HttpPost]
[Consumes("application/xml")]
public IActionResult CreateProduct(Product product)

在上述代码中,CreateProduct Action指定了上下文类型application/xml。路由到这个Action的请求必须指定一个application/xml类型的Content-Type头。没有指定一个application/xml类型的Content-Type头的请求会导致一个 415 Unsupported Media Type响应。

通过应用一个类型约束,[Cosumes]特性也允许一个Action基于即将来临的请求上下文类型来影响它的选择。考虑如下示例:

[ApiController]
[Route("api/[controller]")]
public class ConsumesController : ControllerBase
{
    [HttpPost]
    [Consumes("application/json")]
    public IActionResult PostJson(IEnumerable<int> values) =>
        Ok(new { Consumes = "application/json", Values = values });

    [HttpPost]
    [Consumes("application/x-www-form-urlencoded")]
    public IActionResult PostForm([FromForm] IEnumerable<int> values) =>
        Ok(new { Consumes = "application/x-www-form-urlencoded", Values = values });
}

在上述代码中,ConsumesController 被配置为处理发送给这个URL https://localhost:5001/api/Consumes 的请求。这个控制器的两个Action,PostJson 和 PostForm,会处理相同URL的POST请求。如果没有[Cosumes]特性应用一个类型约束,将会抛出一个不明确的匹配异常。

[Cosumes]特性被应用到两个Action方法。PostJson会处理 以application/json Content-Type 发送的请求。而PostForm会处理以application/x-www-form-urlencoded Content-Type 发送的请求。

额外资源