讲一下Asp.net core MVC2.1 里面的 ApiControllerAttribute
先贴文章链接
正文
ASP.NET Core MVC 2.1 特意为构建 HTTP API 提供了一些小特性,今天主角就是 ApiControllerAttribute
. (注:文章是18年2月份的,所以文章提到了core2.1还没发布)。
0. ApiControllerAttribute 继承自 ControllerAttribute
ASP.NET Core MVC 已经有了ControllerAttribute,这个用来标注一个类型是否是Controller。标注了之后框架就知道哪些是系统里面的Controller了。(框架也有其他方法来获取程序里面的Controller,所以,这个ControllerAttribute不是必须的)。
ApiControllerAttribute
是ControllerAttribute
的子类,所以,框架在处理Controller发现的时候和ControllerAttribute
标注的对象是一样的。
但是,因为ApiControllerAttribute
实现了IApiBehaviorMetadata
接口,所以提供了一些额外的特这些特性是以HTTP Api为出发点的。下面介绍一下这些特性。
1. 自动模型状态验证
这个是重点,框架会帮你自动验证model的state,也就是ModelState
.(注:不过我就是因为用FluentValidation的时候模型验证不管用了出问题了才找到这篇文章的).
框架会为你自动注册ModelStateInvalidFilter
,这个会运行在OnActionExecuting
事件里面(具体来说:在action执行之前,model绑定之后)。他内部会检查ModelState
是否为Valid,如果为InValid会直接返回400 BadRequest,这样就没有必要执行后面的代码,提高效率。
它会自动把model state 放到response里面,content type 是application/problem+json
。当然你也可以自定义,因为毕竟你会有自己的验证,后文会讲。
下面,我们先来举个例子说一下。
- 之前的写法
[Route("[controller]")]
public class BookController : Controller
{
[HttpPost("")]
public IActionResult PostBook([FromBody]Book book)
{
if (ModelState.IsValid) //判断状态
{
return BadRequest(ModelState);
}
//其他代码。。。
}
}
- 现在可以这么写
[ApiController]
[Route("[controller]")]
public class BookController : Controller
{
[HttpPost("")]
public IActionResult PostBook(Book book)
{
//直接写,不用验证modelstate
}
}
顺道说一下,ModelStateInvalidFilter
是个公共类,所以,不用ApiControllerAttribute
也可以使用它。
2.参数绑定策略的自动推断
另一个非常有用的特性是action里面的参数的模型绑定可以自动推断。
ASP.NET Core MVC里面有一个比较令人恼怒的问题你需要手动给参数指定[FromBody]
这个特性,以便让系统知道如何从Request body里面反序列化他们,比如反序列化json。因此,写了很多第三方的库来解决这个问题,比如:
现在,这些可以自动解决了。
除此之外,如果一个参数在route里面定义了,他会自动从先从path,也就是url上尝试绑定,不行的话会去从查询参数上绑定。IFormFlie
默认从form表单上绑定获取。
下面看代码:
- 之前
[Route("[controller]")]
public class BookController : Controller
{
[HttpPost("")]
public IActionResult PostBook([FromBody]Book book)
{
// 写代码
}
}
- 现在
[ApiController]
[Route("[controller]")]
public class BookController : Controller
{
[HttpPost("")]
public IActionResult PostBook(Book book)//FromBody没必要写了
{
// 写代码
}
}
3. 处理multipart/form-data
请求
如果你的action里面的一个参数指定了[FromFile]
特性(这通常是用于文件上传的),框架会自动假设请求是multipart/form-data
。这个是用来解决社区里面提的这个问题。
不过这个也是可选的,只要你自己定义在action上定义一下[Consumes(...)]
。
4.其他
有两个注意点:
- ApiExplorer 的可见性。 默认所有的controller对
ApiExplorer
都是可见的,所以,不影响swagger 等的生成。 - 只是一个基于特性的路由。集中的路由机制不会应用在API controller,框架要求只能使用基于特性的路由,即在action上指定
[Route("XXX")]
的方式。
5. 行为自定义
像MVC框架的大部分组件一样,ApiControllerAttribute
的行为是高度可自定义的。首先,上面说的大部分内容都是可以简单的用 on/off 来切换。
具体的设置是在startup方法里面通过ApiBehaviorOptions
来实现,先来看一下这个类。
public class ApiBehaviorOptions
{
public Func<ActionContext, IActionResult> InvalidModelStateResponseFactory { get; set; }
public bool SuppressModelStateInvalidFilter { get; set; }
public bool SuppressInferBindingSourcesForParameters { get; set; }
public bool SuppressConsumesConstraintForFormFileParameters { get; set; }
}
所有bool类型的属性默认都是false。Suppres有阻止的意思。可以通过以下方法进行设置。
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
options.SuppressConsumesConstraintForFormFileParameters = true;
});
来看一下InvalidModelStateResponseFactory
属性,他是一个返回IActionResult
的Func,通过他,我们可以注入自己的委托来实现需要的返回类型,举个例子。
services.Configure<ApiBehaviorOptions>(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; }
}
讲一下Asp.net core MVC2.1 里面的 ApiControllerAttribute的更多相关文章
- 讲一下Asp.net core MVC2.1 里面的 ApiControllerAttribute (转载)
ASP.NET Core MVC 2.1 特意为构建 HTTP API 提供了一些小特性,今天主角就是 ApiControllerAttribute. (注:文章是18年2月份的,所以文章提到了cor ...
- spring源码分析-core.io包里面的类
前些日子看<深入理解javaweb开发>时,看到第一章java的io流,发觉自己对io流真的不是很熟悉.然后看了下JDK1.7中io包的一点点代码,又看了org.springframewo ...
- ASP.NET Core 发布至Linux生产环境 Ubuntu 系统
ASP.NET Core 发布至Linux生产环境 Ubuntu 系统,之前跟大家讲解了 dotnet publish 发布,而没有将整个系统串起来. 今天就跟大家综合的讲一下ASP.NET Core ...
- ASP.NET Core 应用程序Startup类介绍
Startup类配置服务和应用程序的请求管道. Startup 类 ASP.NET Core应用程序需要一个启动类,按照惯例命名为Startup.在主程序的Web Host生成器(WebHostBui ...
- ASP.NET Core 2.0 : 七.一张图看透启动背后的秘密
为什么我们可以在Startup这个 “孤零零的” 类中配置依赖注入和管道? 它是什么时候被实例化并且调用的? 参数中的IServiceCollection services是怎么来的? 处理管道是怎么 ...
- ASP.NET Core 应用程序Startup类介绍 (转载)
Startup类配置服务和应用程序的请求管道. Startup 类 ASP.NET Core应用程序需要一个启动类,按照惯例命名为Startup.在主程序的Web Host生成器(WebHostBui ...
- Pro ASP.NET Core MVC 第6版 第一章
目录 第一章 ASP.NET Core MVC 的前世今生 ASP.NET Core MVC 是一个微软公司开发的Web应用程序开发框架,它结合了MVC架构的高效性和简洁性,敏捷开发的思想和技术和.N ...
- asp.net core mvc 读取配置文件appsettings.json
上一篇我们将了读取自定义配置文件.这篇我们讲一下asp.net core mvc里读取自带的配置文件 appsettings.json 首先创建个asp.net core mvc项目,项目里有Prog ...
- MiniProfiler 来分析 ASP.NET Core
使用 MiniProfiler 来分析 ASP.NET Core 应用 使用 MiniProfiler 来分析 ASP.NET Core 应用 MiniProfiler(https://minip ...
随机推荐
- JS for循环 if判断、white循环。小练习二
假设一个简单的ATM机的取款过程是这样的:首先提示用户输入密码(password),最多只能输入三次,超过3次则提示用户“密码错误,请取卡”结束交易.如果用户密码正确,再提示用户输入取款金额(amou ...
- hadoop2-elasticsearch的安装
本文主要讲elasticsearch-2.2.1的安装过程. 准备工作: 1.搭建虚拟机 你需要先参考 hadoop2集群环境搭建 把你的虚拟机搭建起来-hadoop环境可以先不用搭建(完成步骤1到步 ...
- CSS矩形、三角形等
1.圆形 CSS代码如下:宽高一样,border-radius设为宽高的一半 #circle { width: 100px; height: 100px; background: red; -moz- ...
- for循环:用turtle画一颗五角星
import turtle # 设置初始位置 turtle.penup() turtle.left(90) turtle.fd(200) turtle.pendown() turtle.right(9 ...
- 在vue中使用sass的配置的方法
1.安装sass的依赖包 npm install --save-dev sass-loader //sass-loader依赖于node-sass npm install --save-dev nod ...
- sv时序组合和时序逻辑
input a; input b; input c; reg d; wire e; reg f; // 时序逻辑,有寄存器 always@(posedge clk)begin 'b1)begin d ...
- 问题:AJAX的send参数里,空格以及它后面的数据在传递时消失(已解决)
今天,我在写关于前端向后台传递一些数字进行排序,并把结果返回到前端的程序.我用的是POST方式,须要在send里面写键值对. 前端和后台都写完,但是,前端传递给后台的数据是一部分,我检查了下,发现获取 ...
- npm修改淘宝原
//修改之前查看一下npm config get registry https://registry.npmjs.org/ //设置源npm config set registry https://r ...
- Chrome+postman+postman interceptor调试
本文使用chrome+postman4.8.3+postman interceptor0.2.23调试使用cookie的请求. postman4.8.3下载地址:https://pan.baidu.c ...
- hadoop源码分析(2):Map-Reduce的过程解析
一.客户端 Map-Reduce的过程首先是由客户端提交一个任务开始的. 提交任务主要是通过JobClient.runJob(JobConf)静态函数实现的: public static Runnin ...