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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    hdu 1199 Color the Ball 离散线段树
    poj 2623 Sequence Median 堆的灵活运用
    hdu 2251 Dungeon Master bfs
    HDU 1166 敌兵布阵 线段树
    UVALive 4426 Blast the Enemy! 计算几何求重心
    UVALive 4425 Another Brick in the Wall 暴力
    UVALive 4423 String LD 暴力
    UVALive 4872 Underground Cables 最小生成树
    UVALive 4870 Roller Coaster 01背包
    UVALive 4869 Profits DP
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/11558525.html
Copyright © 2011-2022 走看看