【译】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/json
和 application/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 发送的请求。
额外资源