我们先创建一个 WebAPI 项目,看看官方给的模板到底有哪些东西

官方给出的模板:

    [Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
} // GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
} // POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
} // PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
} // DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}

同时,在 Startup 类中注册了 Mvc 中间件.

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
} app.UseHttpsRedirection();
app.UseMvc();
}

实际上, 继承 ControllerBase ,特性 [Route] [ApiController] 都是为了提供一些便利功能,一个最"轻量"的 WebAPI 是这样的:

新建一个 TestController:

    public class TestController
{
public string Get()
{
return "hello world";
}
}

啥也没有,很干净.

注册 Mvc 中间件时添加路由:

            //app.UseMvc(route => { route.MapRoute("default", "api/{controller}"); });//不能这样写,这种最轻量的方式,不支持 Restful 风格的请求方式
app.UseMvc(route => { route.MapRoute("default", "api/{controller}/{action}"); });

测试:

当然,我们也可以不在 注册 Mvc 中间件的时候添加路由,还是像官方推荐的那样,在控制器上利用路由特性,这种方式就支持 Restful 风格的请求方式了.

    [Route("api/[controller]")]
public class TestController
{
public string Get()
{
return "hello world";
}
}

那 ControllerBase 提供了哪些便利功能呢?看源码就明白了:

截一小部分图:

[ApiController] 特性则提供如下便利功能:

绑定源参数推理

当没有[ApiController]特性时,参数绑定都默认从QueryString获取.假设有如下控制器和实体类:

    [Route("api/[controller]")]
public class TestController
{
public string Get(Person person, int id, string name, Student student)
{
var temp = new { person, id, name, student };
return JsonConvert.SerializeObject(temp);
}
}
    public class Person
{
public int Id { get; set; } public string Name { get; set; }
} public class Student
{
public int Id { get; set; } public string Name { get; set; }
}

请求结果:

可以看到,所有的参数都绑定上了.

但工作中,复杂类型我们一般都是 post 提交,写在 body 里面.

现在我们改用post提交 ,稍微修改一下 action :

    [Route("api/[controller]")]
public class TestController
{
public string Get(Person person)
{
return JsonConvert.SerializeObject(person);
}
}

请求:

结果没有绑定上:

 这也证明了 在没有 [ApiController] 特性时,默认都是从 QueryString 获取参数来绑定.

上述例子要想绑定成功,需要给 action 的入参打上 [FromBody] 特性:

        public string Get([FromBody]Person person)
{
return JsonConvert.SerializeObject(person);
}

请求结果:

ASP.NET Core 的绑定特性似乎比 ASP.NET 多了一些,下面是官网给的:

如果 Controller 上应用了 [ApiController] 特性,那么框架会根据参数类型自动选择绑定特性.

现在我们给 TestController 应用 [ApiController] 特性,同时删掉 Action 上的 [FromBody] 特性:

    [Route("api/[controller]")]
[ApiController]
public class TestController
{
public string Get(Person person)
{
return JsonConvert.SerializeObject(person);
}
}

请求结果:

至于自动选择绑定特性的规则,我也没有全部测试,不过我感觉应该和 ASP.NET 是一样的.

但是,有个地方不一样,不知道算不算 ASP.NET Core 的优化:

对于之前的 ASP.NET WebAPI ,如果 QueryString 的参数没有涵盖 Action 上定义的所有参数,那么是请求不到该 Action 的.

比如,这是一个 ASP.NET WebAPI 控制器,Get 方法定义了两个入参:

    public class TestController : ApiController
{
public string Get(int id,string name)
{
var temp = new {id, name};
return JsonConvert.SerializeObject(temp);
}
}

那么,如果我们的 QueryString 只传递了其中一个,是请求不到 Get 方法的.

但是, ASP.NET Core 是可以的:

上面提到的这个自动选择绑定特性的规则,可以通过代码来禁止(红色部分,其余的是禁用 [ApiController] 特性提供的其他便利功能的):

            services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[].Link =
"https://httpstatuses.com/404";
});

至于其他便利功能,可以查看官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/web-api/?view=aspnetcore-2.2

其实我写的这些,大多数都是抄的官方文档.

ASP.NET Core 2.2 基础知识(十三) WebAPI 概述的更多相关文章

  1. ASP.NET Core 2.2 基础知识(十八) 托管和部署 概述

    为了方便演示,以 .NET Core 控制台应用程序讲解. 我们新建一个控制台应用程序,安装 "Newtonsoft.Json" Nuget 包,然后右键点击该项目,选择" ...

  2. ASP.NET Core 2.2 基础知识(十二) 发送 HTTP 请求

    可以注册 IHttpClientFactory 并将其用于配置和创建应用中的 HttpClient 实例. 这能带来以下好处: 提供一个中心位置,用于命名和配置逻辑 HttpClient 实例. 例如 ...

  3. ASP.NET Core 2.2 基础知识(十六) SignalR 概述

    我一直觉得学习的最好方法就是先让程序能够正常运行,才去学习他的原理,剖析他的细节. 就好像这个图: 所以,我们先跟着官方文档,创建一个 SignalR 应用: https://docs.microso ...

  4. ASP.NET Core 2.2 基础知识(十四) WebAPI Action返回类型(未完待续)

    要啥自行车,直接看手表 //返回基元类型 public string Get() { return "hello world"; } //返回复杂类型 public Person ...

  5. ASP.NET Core 2.2 基础知识(十一) ASP.NET Core 模块

    ASP.NET Core 应用与进程内的 HTTP 服务器实现一起运行.该服务器实现侦听 HTTP 请求,并在一系列请求功能被写到 HttpContext 时,将这些请求展现到应用中. ASP.NET ...

  6. ASP.NET Core 2.2 基础知识(十) Web服务器 - Kestrel

    ASP.NET Core 应用与进程内的 HTTP 服务器实现一起运行.该服务器实现侦听 HTTP 请求,并在一系列请求功能被写到 HttpContext 时,将这些请求展现到应用中. ASP.NET ...

  7. ASP.NET Core 2.2 基础知识(九) 使用托管服务实现后台任务

    在 ASP.NET Core 中,后台任务作为托管服务实现.托管服务是一个类,而且必须实现 IHostedService 接口,该接口定义了两个方法: StartAsync(CancellationT ...

  8. ASP.NET Core 2.2 基础知识(八) 主机 (未完待续)

    主机负责应用程序启动和生存期管理.共有两个主机 API : 1.Web 主机 : 适用于托管 Web 应用,基于 IWebHostBuilder ; 2.通用主机 : 适用于托管非 Web 应用. 基 ...

  9. ASP.NET Core 2.2 基础知识(六) 配置(内含MySql+EF)

    先上一段代码,了解一下 .NET Core 配置数据的结构. 新建一个 控制台项目,添加一个文件 json.json ,文件内容如下: { "country": "cn& ...

随机推荐

  1. MySQL之数据库及表的修改和删除

    本文章来自实验楼的操作过程和其中相应地解释.(博客园不知道怎么回事,上传图片总是失败.) 一.对数据库修改 1)删除数据库的命令为:DROP DATABASE 数据名; 二.对表的修改 1)重命名一张 ...

  2. JS Cookie相关操作

    function setCookie(cookieName, cookieValue, expires) { // 设置Cookie function getCookieName(cookieName ...

  3. CSS属性中cursor:hand

    在 IE 下设置鼠标为手型的方法: cursor: hand,但是在 FIREFOX 中是无效的,解决方法是在FIREFOX中设置: cursor: pointer. 而这个pointer 值在IE和 ...

  4. [06] 盒模型 + auto 居中 + 垂直合并

    1.盒模型 盒子模型有两种,分别是 ie 盒子模型和标准 w3c 盒子模型. 标准(W3C)模型中:CSS中的宽(width) = 内容 (content)的宽 CSS中的宽(width) = 内容( ...

  5. 知问前端——日历UI(二)

    datapicker外观选项 属性 默认值/类型 说明 disabled false/布尔值 禁用日历 numberOfMonths 1/数值 日历中同时显示的月份个数.默认为1,如果设置3就同时显示 ...

  6. 通过 CLI 搭建 ghost

    参考: ghost 官网 系统架构说明 架构 架构说明 本实践将 web 接入, nodejs 服务, 数据库分离, 适合生产环境场景. nginx 接入请求, 反向代理后端 nodejs 服务 no ...

  7. swt MouseAdapter

    Exception in thread "main" java.lang.Error: Unresolved compilation problem:     The method ...

  8. HDU1217 (Floyd简单变形)

    Arbitrage Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total S ...

  9. android 调试 native 程序的方法

    一.背景 首先说需求,这个需求非常常见,就是android上需要的一个功能,linux已经有开源代码而且非常稳定,希望能直接porting过去使用,这个程序是pure c 的代码,也就是说,跟andr ...

  10. linux下面某些常用命令的用法【转】

    转自:http://blog.csdn.net/luo3532869/article/details/7584290 ls 命令用于常看目录,用法:ls [选项][目录或文件]例:使用ls命令显示/h ...