• ASP.NET Core 2.2 基础知识(十三) WebAPI 概述


    我们先创建一个 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[404].Link =
                            "https://httpstatuses.com/404";
                    });

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

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

  • 相关阅读:
    vscode英文显示设置为中文语言
    vscode各插件使用-背景图-scss
    公众号关联小程序
    js点击遮罩空白区域关闭,点击遮罩内元素不关闭
    swiper使用-点击跳转指定页
    小程序内部引导关注公众号实现方法
    jq赋值input值为空
    sass中代码使用
    Sources”参数中指定了多次。“Sources”参数不支持重复项
    将已存在小程序项目添加云开发配置
  • 原文地址:https://www.cnblogs.com/refuge/p/10232544.html
Copyright © 2020-2023  润新知