ASP.NET Core MVC 2.1将附带一个很好的小功能,专门针对构建HTTP API的人--ApiControllerAttribute。虽然2.1的稳定版本还没有在这里,但我们已经可以看看幕后 - 这个功能做了什么,以及它如何帮助您编写Web API。
ASP.NET Core MVC已经有一个名为ControllerAttribute的属性。它用于将给定类型注释为控制器候选者,因此框架将使用类型的方法来发现潜在的端点(框架还具有其他控制器发现方式,因此属性不是必需的)。
ApiControllerAttribute实际上是ControllerAttribute的子类,因此在类型上使用它会强制类型以相同的方式参与控制器发现过程。
但是,它还带来了一些额外的功能,这是因为ApiControllerAttribute还实现了一个名为IApiBehaviorMetadata的接口。对于使用IApiBehaviorMetadata注释的每种类型,该框架将提供一些额外的,以HTTP API为中心的功能。这些将在下面讨论。
这是一个很大的问题。该框架将自动为您验证模型状态。这是微软的各种基于ASP.NET的框架中的一个问题,因为,永远。你总是需要手动,如果你一直在阅读这篇博客,我过去曾在博客中写过这篇文章。
在这种情况下,框架将自动为您做什么,它将为您注册一个ModelStateInvalidFilter,它在OnActionExecuting事件期间运行(因此在您运行操作之前,但在模型绑定之后)。它将在内部检查ModelState是否有效,并立即向调用者产生400 Bad Request响应(短路)。
构造响应的方式是模型状态简单地填充到响应中,分配给它的内容类型是application / problem + json。您有机会自定义它,因为您可以注册自己的验证设备(稍后会详细介绍)。
总的来说,该功能意味着以下代码:
[Route("[controller]")]
public class BookController : Controller
{
[HttpPost("")]
public IActionResult PostBook([FromBody]Book book)
{
if (ModelState.IsValid)
{
return BadRequest(ModelState);
}
// omitted for brevity
}
}
现在可以简化,因为此代码段具有完全相同的行为(模型状态的自动验证):
[ApiController]
[Route("[controller]")]
public class BookController : Controller
{
[HttpPost("")]
public IActionResult PostBook(Book book)
{
// omitted from brevity
}
}
值得添加的一件事是,ModelStateInvalidFilter是一个公共类,可以在MVC配置中自由使用(例如,作为针对MvcOptions的全局过滤器插入),即使不选择使用ApiControllerAttribute也是如此。
Web API开发的另一个非常有用的功能是您的操作的各种参数将自动推断其绑定模型。
ASP.NET Core MVC最大的烦恼之一是您必须使用[FromBody]属性手动注释操作的复杂参数,以支持从请求主体反序列化它们 - 例如JSON有效负载。因此,已经创建了各种第三方解决方案来解决这个问题。现在自动处理。
除此之外,如果路径中存在参数,它将自动推断为从路径绑定,否则将假定为查询字符串参数。IFormFile参数将自动从表单绑定。
所以不再需要这个:
[Route("[controller]")]
public class BookController : Controller
{
[HttpPost("")]
public IActionResult PostBook([FromBody]Book book)
{
// omitted from brevity
}
}
因为这个(终于!)开箱即用:
[ApiController]
[Route("[controller]")]
public class BookController : Controller
{
[HttpPost("")]
public IActionResult PostBook(Book book)
{
// omitted from brevity
}
}
如果您的操作上的参数使用[FormFile]属性进行注释(通常是为文件上传完成),则框架现在将自动假定端点使用multipart / form-data请求。这样可以省去手动操作的麻烦。
如果您在操作上定义自己的[Consumes(...)]属性,则可以选择此选项。在这种情况下,您的价值优先。
其他一些小笔记:
与MVC框架中的大多数内容一样,ApiControllerAttribute的开箱即用行为是高度可定制的。首先,几乎所有上述主要功能都可以打开/关闭。
这是在应用程序启动时通过ApiBehaviorOptions完成的。选项类型如下所示:
public class ApiBehaviorOptions
{
public Func InvalidModelStateResponseFactory { get; set; }
public bool SuppressModelStateInvalidFilter { get; set; }
public bool SuppressInferBindingSourcesForParameters { get; set; }
public bool SuppressConsumesConstraintForFormFileParameters { get; set; }
}
默认情况下,所有布尔标志都设置为false。然后,您可以根据需要配置它们,例如:
services.Configure(options =>
{
options.SuppressModelStateInvalidFilter = true;
options.SuppressConsumesConstraintForFormFileParameters = true;
});
请注意,选项配置还允许您注入自己的模型验证委托,您将获得当前的ActionContext,并且应该生成您自己的IActionResult。下面显示了一个示例,我们仍然依赖于ModelState,但是将项目投射到我们自己的自定义响应类型上:
services.Configure(options =>
{
options.InvalidModelStateResponseFactory = actionContext =>
{
var errors = actionContext.ModelState
.Where(e => e.Value.Errors.Count > 0)
.Select(e => new Error
{
Name = e.Key,
Message = e.Value.Errors.First().ErrorMessage
}).ToArray();
return new BadRequestObjectResult(errors);
}
});
class Error
{
public string Name { get; set; }
public string Message { get; set; }
}
原文:https://www.strathweb.com/2018/02/exploring-the-apicontrollerattribute-and-its-features-for-asp-net-core-mvc-2-1/