栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

讲一下Asp.net core MVC2.1 里面的 ApiControllerAttribute

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

讲一下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。因此,写了很多第三方的库来解决这个问题,比如:

  • WebApiContrib.Core.Formatter.Bson

  • WebApiContrib.Core.Formatter.Csv

  • 其他不写了,,就举个例子

现在,这些可以自动解决了。

除此之外,如果一个参数在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.其他

有两个注意点:

  1. ApiExplorer 的可见性。 默认所有的controller对ApiExplorer都是可见的,所以,不影响swagger 等的生成。

  2. 只是一个基于特性的路由。集中的路由机制不会应用在API controller,框架要求只能使用基于特性的路由,即在action上指定[Route("XXX")]的方式。

5. 行为自定义

像MVC框架的大部分组件一样,ApiControllerAttribute的行为是高度可自定义的。首先,上面说的大部分内容都是可以简单的用 on/off 来切换。

具体的设置是在startup方法里面通过ApiBehaviorOptions来实现,先来看一下这个类。

    public class ApiBehaviorOptions
    {        public Func InvalidModelStateResponseFactory { get; set; }        public bool SuppressModelStateInvalidFilter { get; set; }        public bool SuppressInferBindingSourcesForParameters { get; set; }        public bool SuppressConsumesConstraintForFormFileParameters { get; set; }
    }

所有bool类型的属性默认都是false。Suppres有阻止的意思。可以通过以下方法进行设置。

services.Configure(options =>
{
    options.SuppressModelStateInvalidFilter = true;
    options.SuppressConsumesConstraintForFormFileParameters = true;
});

来看一下InvalidModelStateResponseFactory属性,他是一个返回IActionResult的Func,通过他,我们可以注入自己的委托来实现需要的返回类型,举个例子。

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.cnblogs.com/sheldon-lou/p/9495377.html

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/231540.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号