zoukankan      html  css  js  c++  java
  • 第十八节:Asp.Net Core WebApi基础总结和请求方式

    一. 基础总结

    1.Restful服务改造

      Core下的WebApi默认也是Restful格式服务,即通过请求方式(Get,post,put,delete)来区分请求哪个方法,请求的URL中不需要写方法名。 但是我们不喜欢这种方式,所以我们将默认的路由规则 [Route("api/[controller]")] 改为: [Route("api/[controller]/[action]")]

    2.基本格式

    继承 ControllerBase 类,需要加特性[ApiController].

    (1) 特性[ApiController]的作用:

      a.特性路由要求,和[Route]成对出现,有了它,通过 UseMvc 定义的传统路由或通过 Startup.Configure 中的 UseMvcWithDefaultRoute 访问操作均无效。

      b.模型验证错误自动触发 HTTP 400 响应

      c.绑定源参数推理(如果没有 [ApiController] 属性,同时也没有 [FromQuery][FromBody]等 的绑定源属性,ASP.NET Core 运行时会尝试使用复杂对象模型绑定器。)

      d.Multipart/form-data 请求推理

      f.错误状态代码的问题详细信息

    (2) 特性[ApiController]的作用位置:

      a.作用于controller

      b.作用于程序集,服务于整个项目。在Startup类上的namespace上添加:[assembly: ApiController]

    注:它不能作用action上。

    PS:MVC中的Controller类继承ControllerBase类,实现了IActionFilter, IFilterMetadata, IAsyncActionFilter, IDisposable接口。

    3.路由规则

      详见  第二十节:Asp.Net Core WebApi和MVC 路由规则比较

    4.常见的特性

      [Route] 指定控制器或操作的 URL 模式。

      [Bind] 指定要包含的前缀和属性,以进行模型绑定。

      [HttpGet] [HttpPost]标识支持 HTTP GET 等操作谓词的操作。

      [Consumes] 指定某个操作接受的数据类型。

      [Produces] 指定某个操作返回的数据类型。

    5.绑定源参数推理

      [FromBody] 实体JSON格式的获取,和不加效果相同

      [FromForm] 请求正文中的表单数据

      [FromQuery] 请求查询字符串参数,Get请求的时候,用实体接受需要加

      [FromHeader] 请求标头

      [FromRoute] 当前请求中的路由数据

      [FromServices] 作为操作参数插入的请求服务,即将对象注入到方法中

    6.允许跨域

      同Core MVC相同,详见:https://www.cnblogs.com/yaopengfei/p/11191938.html

    7.过滤器

      同Core MVC相同,详见:https://www.cnblogs.com/yaopengfei/p/11232921.html, 但webapi中页面相关的过滤器不适用

    二. Get和Post请求

    1. Get请求

      前端JS发送Get请求的时候,后台可以分参数接收,也可以用实体接收,但是需要在实体的前面加上[FromQuery]。

     注:不能用dynamic接收,不管怎么处理都报错。

    案例测试:

     (1).分参数接收,可以正常访问。

     (2).用实体类接收,前面加[FromQuery],可以正常访问(否则报415)。

     (3).用dynamic接收,前面什么不加,报错415,前面加[FromQuery],也报错,报500。

    服务器端代码:

     1     [Route("api/[controller]/[action]")]
     2     [ApiController]
     3     public class FirstController : ControllerBase
     4     {
     5         /******************************************下面是测试Get请求的相关方法***************************************************/
     6 
     7         [HttpGet]
     8         public string GetInfor1(string userName, string pwd)
     9         {
    10             return $"{userName}+{pwd}";
    11         }
    12 
    13         [HttpGet]
    14         public string GetInfor2([FromQuery]UserInfor model)
    15         {
    16             return $"{model.userName}+{model.pwd}";
    17         }
    18         [HttpGet]
    19         //加上[FromQuery]也报错
    20         public string GetInfor3([FromQuery]dynamic model)
    21         {
    22             return $"{model.userName}+{model.pwd}";
    23         }
    24  
    25     }

    前端代码:

     1             //一.下面是Get请求的测试
     2             //1. 分参数接收,可以正常访问
     3             $("#getBtn1").click(function () {
     4                 $.ajax({ url: "https://localhost:44387/api/First/GetInfor1", type: "get", data: { userName: "admin", pwd: "123456" }, success: function (data) { console.log(data); } });
     5             });
     6             //2. 用实体类接收,前面加[FromQuery],可以正常访问(否则报415)
     7             $("#getBtn2").click(function () {
     8                 $.ajax({ url: "https://localhost:44387/api/First/GetInfor2", type: "get", data: { userName: "admin", pwd: "123456" }, success: function (data) { console.log(data); } });
     9             });
    10             //3. 用dynamic接收,前面什么不加,报错415,前面加[FromQuery],也报错,报500
    11             $("#getBtn3").click(function () {
    12                 $.ajax({ url: "https://localhost:44387/api/First/GetInfor3", type: "get", data: { userName: "admin", pwd: "123456" }, success: function (data) { console.log(data); } });

    2. Post请求

      前端JS发送Post请求的时候,可能是表单提交,也可能是JOSN格式提交,所以下面要分情况讨论:默认情况下在我们注入MVC服务时被配置使用的时JsonInputFormatter,即实体默认接受JSON格式的数据,我们如果想让它接受表单数据,需要在实体前面加[FromForm].

     (1) 接收JSON格式:实体前面什么也不加 或者 实体前面加[FromBody]

     (2) 接收表单格式: 实体前面加[FromForm]

    注:不能分参数接收!! 用dynamic接收的时候,只能处理前端JOSN格式的数据,加[FromBody]或者不加都行, 不能处理前端表单格式数据!!

    案例测试:

     (1).一个参数的情况,后台分参数接收,均拿不到值

     (2).表单提交,实体前面什么也不加 或者 实体前面加[FromForm],Login1 和 Login2 均报415,Login3可以正常访问

     (3).JSON提交,实体前面加[FromBody],Login1,Login2正常访问,Login3能访问通,但是后台拿不到值,都为空

     (4).JOSN格式,后台用dynamic能接收,加[FromBody]或者不加都可以接收

     (5).表单格式,后台用dynamic不能接收,加[FromForm]或者不加都报500,报错。

    服务器端代码:

     1     [Route("api/[controller]/[action]")]
     2     [ApiController]
     3     public class FirstController : ControllerBase
     4     {
     5      
     6         /******************************************下面是测试Post请求的相关方法***************************************************/
     7 
     8         [HttpPost]
     9         public string Login0(string userName)
    10         {
    11             return $"{userName}";
    12         }
    13 
    14         [HttpPost]
    15         public string Login1(UserInfor model)
    16         {
    17             return $"{model.userName}+{model.pwd}";
    18         }
    19 
    20         [HttpPost]
    21         public string Login2([FromBody]UserInfor model)
    22         {
    23             return $"{model.userName}+{model.pwd}";
    24         }
    25 
    26         [HttpPost]
    27         public string Login3([FromForm]UserInfor model)
    28         {
    29             return $"{model.userName}+{model.pwd}";
    30         }
    31         [HttpPost]
    32         public string Login4([FromBody]dynamic model)
    33         {
    34             return $"{model.userName}+{model.pwd}";
    35         }
    36 
    37         [HttpPost]
    38         public string Login5([FromForm]dynamic model)
    39         {
    40             return $"{model.userName}+{model.pwd}";
    41         }
    42     }

    前端代码:

     1              //二.下面是Post请求的测试
     2             //(Post请求默认情况下为:ContentType = "application/x-www-form-urlencoded"提交表单的形式,如果要发送JOSN格式,需要加上参数contentType: 'application/json')
     3             //PS: { userName: "admin", pwd: "123456" } 这就是一个JSON对象,也可以叫实体
     4 
     5             //1. 一个参数的情况,后台分参数接收,均拿不到值
     6             $("#postBtn0").click(function () {
     7                 //1.1 正常拼接,可以访问通,但是拿不到userName的值
     8                 //$.ajax({ url: "https://localhost:44387/api/First/Login0", type: "Post", data: { userName: "admin" }, success: function (data) { console.log(data);  } });
     9                 //1.2 没有键,只有值,可以访问通,但是拿不到userName的值 (这里同.Net 平台下的WebApi不同)
    10                 $.ajax({ url: "https://localhost:44387/api/First/Login0", type: "Post", data: { "": "admin" }, success: function (data) { console.log(data); } });
    11             });
    12 
    13             //2. 表单提交,Login1 和 Login2 均报415,Login3可以正常访问
    14             $("#postBtn1").click(function () {
    15                 $.ajax({ url: "https://localhost:44387/api/First/Login1", type: "Post", data: { userName: "admin", pwd: "123456" }, success: function (data) { console.log("Login1:" + data); } });
    16                 $.ajax({ url: "https://localhost:44387/api/First/Login2", type: "Post", data: { userName: "admin", pwd: "123456" }, success: function (data) { console.log("Login2:" + data); } });
    17                 $.ajax({ url: "https://localhost:44387/api/First/Login3", type: "Post", data: { userName: "admin", pwd: "123456" }, success: function (data) { console.log("Login3:" + data); } });
    18             });
    19 
    20             //3.JSON提交,Login1,Login2正常访问,Login3能访问通,但是后台拿不到值,都为空
    21             $("#postBtn2").click(function () {
    22                 //将post请求指定为contentType: 'application/json',且传递的参数格式化成Json字符串,则可以正常访问
    23                 $.ajax({ url: "https://localhost:44387/api/First/Login1", type: "Post", contentType: 'application/json', data: JSON.stringify({ userName: "admin", pwd: "123456" }), success: function (data) { console.log("Login1:" + data); } });
    24                 $.ajax({ url: "https://localhost:44387/api/First/Login2", type: "Post", contentType: 'application/json', data: JSON.stringify({ userName: "admin", pwd: "123456" }), success: function (data) { console.log("Login2:" + data); } });
    25                 $.ajax({ url: "https://localhost:44387/api/First/Login3", type: "Post", contentType: 'application/json', data: JSON.stringify({ userName: "admin", pwd: "123456" }), success: function (data) { console.log("Login3:" + data); } });
    26 
    27             });
    28 
    29             //4.JOSN格式,后台用dynamic能接收,加[FromBody]或者不加都可以接收
    30             $("#postBtn3").click(function () {
    31                 //将post请求指定为contentType: 'application/json',且传递的参数格式化成Json字符串,则可以正常访问
    32                 $.ajax({ url: "https://localhost:44387/api/First/Login4", type: "Post", contentType: 'application/json', data: JSON.stringify({ userName: "admin", pwd: "123456" }), success: function (data) { console.log("JSON:" + data); } });
    33             });
    34             //5.表单格式,后台用dynamic不能接收,加[FromForm]或者不加都报500
    35             $("#postBtn4").click(function () {
    36                 $.ajax({ url: "https://localhost:44387/api/First/Login5", type: "Post", data: { userName: "admin", pwd: "123456" }, success: function (data) { console.log("表单:" + data); } });
    37             });

    3.总结

      Get请求,可以分参数接收,也可以用实体接收,需要在实体的前面加上[FromQuery]。

      POST请求,用实体接收,针对js默认的表单提交方式,实体前面加[FromForm];针对js的JSON格式的提交方式,实体前面什么也不加 或者 实体前面加[FromBody]。

    4. 返回值的问题(补充)

      用Content标记json类型和直接返回序列化字符串的区别。用 Content(jsonData, "application/json"); 标记,前端什么不用加,可以直接点出来的。

       /// <summary>
            /// 前端不能直接点出来
            /// </summary>
            /// <returns></returns>
            [HttpGet]
            public string GetGoodById1()
            {
                var myData = new
                {
                    status = "ok",
                    goods = new UserInfor()
                    {
                        userName = "apple",
                        pwd = "12345"
                    }
                };
                var jsonData = JsonConvert.SerializeObject(myData);
                return jsonData;
            }
    
            /// <summary>
            /// 前端可以直接 点出来
            /// </summary>
            /// <returns></returns>
            [HttpGet]
            public IActionResult GetGoodById2()
            {
                var myData = new
                {
                    status = "ok",
                    goods = new UserInfor()
                    {
                        userName = "apple",
                        pwd = "12345"
                    }
                };
                var jsonData = JsonConvert.SerializeObject(myData);
                return Content(jsonData, "application/json");
            }

    前端调用

             $("#rBtn1").click(function () {
                    $.ajax({
                        url: "https://localhost:44387/api/First/GetGoodById1", type: "get", data: { userName: "admin", pwd: "123456" },  success: function (data) {
                            console.log(data);
                            //不能直接点出来
                            console.log(data.status);
                        }
                    });
                    $.ajax({
                        url: "https://localhost:44387/api/First/GetGoodById1", type: "get", data: { userName: "admin", pwd: "123456" }, dataType: "json", success: function (data) {
                            console.log(data);
                            //加上dataType: "json",就能直接点出来
                            console.log(data.status);
                        }
                    });
                });
                $("#rBtn2").click(function () {
                    $.ajax({
                        url: "https://localhost:44387/api/First/GetGoodById2", type: "get", data: { userName: "admin", pwd: "123456" }, success: function (data) {
                            console.log(data);
                            //能直接点出来
                            console.log(data.status);
                        }
                    });
                });

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    Kotlin学习系列(三)
    获取Android设备标识符
    Kotlin学习系列(二)
    ijkplayer实现IMediaDataSource
    Fresco添加HTTP请求头
    Kotlin学习系列(一)
    完整的Android MVP开发之旅
    Marshmallow权限使用
    APP设计与开发(ui篇)
    下载Android源码
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/11558525.html
Copyright © 2011-2022 走看看