zoukankan      html  css  js  c++  java
  • 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

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

  • 相关阅读:
    最大子数组求和并进行条件组合覆盖测试
    Ubuntu 16.04 c++ Google框架单元测试
    The directory '/home/stone/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If execu
    Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/cache/app-info -a -e /usr/bin/appstreamcli; then appstreamcli refresh > /dev/null; fi'
    个人博客作业三:微软小娜APP的案例分析
    补交 作业一
    补交 作业二:个人博客作业内容:需求分析
    嵌入式软件设计第12次实验报告
    嵌入式软件设计第11次实验报告
    嵌入式软件设计第10次实验报告
  • 原文地址:https://www.cnblogs.com/refuge/p/10232544.html
Copyright © 2011-2022 走看看