zoukankan      html  css  js  c++  java
  • 【WebApi系列】详解WebApi如何传递参数

    WebApi系列文章

    【01】浅谈HTTP在WebApi开发中的运用

    【02】聊聊WebApi体系结构

    【03】详解WebApi参数的传递

    【04】详解WebApi测试和PostMan

    【05】浅谈WebApi Cores

    【06】详解WebApi 异常处理

    【07】用WebAPI写个基于EF的CURD

    【08】浅谈WebAPI身份认证

    【09】详解系列化和模型绑定

    【10】浅谈WebApi如何配合Mvc有效工作

    【11】浅谈API Reference

    【12】浅谈接口在软件架构中的作用

    【13】浅谈WebApi和WebService的比较

    【14】浅谈如何设计一个良好的接口

                                                                         


    阅读目录

    一     概述

    二    Get

        1   基础数据类型

            1.1  方法只含一个形参

            1.2  方法含多个形参

        2   实体对象类型

        3   实体对象和基础数据类型混合

        4   最小满足原则

        5   url长度限制

        6   Get规范化

        7    关于实体作为参数传递的拓展

             7.1   借助[FromUri]特性传递实体

             7.2   系列化和反系列化传递实体

    三    Post

        1   基本数据类型传递

             1.1   [FromBody]单个参数传递

             1.2  Dynamic单个参数传递

        2   实体作为参数传递

        3   实体集合作为参数传递

        4   数组作为参数传递

        5   小结

    四   总结

     一 概述

    一般地,我们在研究一个问题时,常规的思路是为该问题建模;我们在研究相似问题时,常规思路是找出这些问题的共性和异性。基于该思路,我们如何研究WebApi参数传递问题呢?

    首先,从参数本身来说,种类较为多(如int,double,float,string,array,Object等),且有些类型较为复杂(如值类型和引用类型的机制等);

    其次,从基于WebApi的Http请求方法来说,种类多且不尽相同(如Get,post,Delete,put,head等),在上一篇文章 :【WebApi系列】浅谈HTTP在WebApi开发中的运用  中,我们简要描述了Http请求的20个方法;

    ..........

    如此复杂且不尽相同,关于WebApi参数传递,我们该选择什么作为切入点来研究呢?基于我们上面提到的研究思路,我们想到了.NET Framework框架,那么,我们来看看基于.NET Framework框架的的WebApi

    模板是怎样的呢?

    请按图中步骤操作

    我们来看看Values控制器是怎样的

     1  public class ValuesController : ApiController
     2     {
     3         // GET api/values
     4         public IEnumerable<string> Get()
     5         {
     6             return new string[] { "value1", "value2" };
     7         }
     8 
     9         // GET api/values/5
    10         public string Get(int id)
    11         {
    12             return "value";
    13         }
    14 
    15         // POST api/values
    16         public void Post([FromBody]string value)
    17         {
    18         }
    19 
    20         // PUT api/values/5
    21         public void Put(int id, [FromBody]string value)
    22         {
    23         }
    24 
    25         // DELETE api/values/5
    26         public void Delete(int id)
    27         {
    28         }
    29     }

    从Values控制器,我们不难得出如下几个结论:

    (1)WebApi常规方法为四个:Get,Post,Put和Delete;

    (2)四种方法的参数可归结为两大类:url传递(Request-url)和Body(Request-body)传递;

    (3)基于(2),我们将四种方法的参数传递归为两大类,而这两大类又集中在Get和Post中体现了(Put是Get和Post的组合,Delete与Get类似);

     

    其实,分析到现在,我们很容易找得到了研究WebApi参数传递的切入点?研究Get和Post方法参数传递即可。是的,没错,我们本篇文章就是基于Get和Post方法的参数传递,前者对应Request-url,后者对应Reqeust-Body。

    二  Get

    1  基础数据类型


     

    1.1  方法只含一个形参(参数传得进去)

    ajax

    $(document).ready(function () {
       $("#FindProdcutDetail").click(function () {
           $.ajax({
                   type: "Get",
                   //url: "/api/Default/GetProductDetails?ProductCode=JX80869"
                   url: "/api/Default/GetProductDetails",
                   data: { "ProductCode":"JX80869"}
                })
            })           
       })

    Result

     总结

    (1)当Get方法形参为一个且为基本数据类型时,Get方法能接受外部传递的值

    (2)Get传值的本质是通过url字符串拼接,如上两两种url形式的传递的结果都是一样

    url形式1

    url: "/api/Default/GetProductDetails?ProductCode=JX80869"

    url形式2

    url: "/api/Default/GetProductDetails",
    data: { "ProductCode":"JX80869"}

    我们用Goole Chrome来看看结果,发现url形式1和url形式2均一致

    (3)Get传递参数本质是url字符串拼接,Request-Head头部传递,Request-Body中不能传递(这是与Post方法的本质区别),我们举两个例子

    例子1:我们将形参添加[FromBody]属性后,值传递不进去

    例子2:我们用PostMan来测试,发现PostMan中,Get方法参数Body为灰色,是不能选中的

     

    1.2  方法含有多个形参(参数传得进去)

    $(document).ready(function () {
       $("#FindProdcutDetail").click(function () {
          $.ajax({
                   type: "Get",
                   url: "/api/Default/GetProductDetails",
                   data: { "ProductCode": "JX80869","ProductName":"YaGao"}
                })
            })
      })

    result

    2   实体对象类型(参数传不进去)


     model

     1  public class ProductDetail
     2     {
     3         //产品编码
     4         [Required]
     5         public string ProductCode { get; set; }
     6         //产品名称
     7         [Required]
     8         public string ProductName { get; set; }
     9         //产品价格
    10         [Required]
    11         public double  ProductPrice{ get; set; }
    12     }

    ajax

    $(document).ready(function () {
        var productDetail = { "ProductName": "YaGao", "ProductCode": "JX80869", "ProductPrice": 40.5};
            $("#FindProdcutDetail").click(function () {
                $.ajax({
                        type: "Get",
                        url: "/api/Default/ProductDetails",
                        data: productDetail
                    })
                })
            })

    result:

     分析

    3   实体对象和基础数据类型混合(实体传不进去,基础数据能传递进去)


     ajax

    1 $(document).ready(function () {
    2    $("#FindProdcutDetail").click(function () {
    3        $.ajax({
    4                 type: "Get",
    5                 url: "/api/Default/GetProductDetails",
    6                 data: { "_productDetail": "ObjectEntity","ProductName":"YaGao"}
    7              })
    8         })
    9     })

     result

    4  最小满足原则(参数传得进去)


     所谓“最小满足原则”,指外部参数必须至少满足被调用方法的形参(形参个数,形参类型和形参名字),换句话说,被调用方法具有的形参,外部参数必须传递进来,被调用方法没有

    的形参,外部参数传递与否都可以,否则将会产生状态码404错误,用数学集合的思路来理解的话,被调用方法的形参相当于外部参数的子集。如下例子,我们举一个真子集的例子,

    即外部传递参数的个数大于被调方法的的形参个数。

    Ajax

     $(document).ready(function () {
        $("#FindProdcutDetail").click(function () {
           $.ajax({
                    type: "Get",
                    url: "/api/Default/GetProductDetails",
                    data: {"ProductCode": "JX00034", "ProductName": "YaGao", "ProductPrice": 20.5, "PrudcutType": "Daily Necessities"}
                    })
                })
            })

    result

     分析:主要原因是路由规则,路由从url里面取参数与aciton参数匹配,直到匹配满足为止,具体详细深入内容,在【WebApi系列】路由章节分析。

    5  url长度限制


     url参数长度是有一定限制的,当超过一定长度,会报404错误

    ajax

     $(document).ready(function () {
                $("#FindProdcutDetail").click(function () {
                    $.ajax({
                        type: "Get",
                        url: "/api/Default/GetProductDetails",
                        data: {
                            "ProductCode":
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 
                        }
                    })
                })
            })

    result

    6  Get规范化


     关于Get类型规范化,应注意两点,避免不必要的错误或异常:(1)方法的命名尽量采用:“Get+方法名”的形式 (2)在每个方法上加上特性[HttpGet]。

    例子:我们去掉[HttpGet]特性和方法前的Get,看看情况什么怎样的

    ajax

    $(document).ready(function () {
        $("#FindProdcutDetail").click(function () {
            $.ajax({
                     type: "Get",
                     url: "/api/Default/ProductDetails",
                     data: {"ProductCode": "JX00034 "}
                 })
             })
        })

    Controller

    1 public class DefaultController : ApiController
    2     {
    3         4         //[HttpGet]
    5         public string ProductDetails(string ProductCode)
    6         {
    7             return "values";
    8         }
    9     }

     Result

    7  关于实体作为参数传递的拓展


     

    7.1  借助[FromUri]特性传递实体

    ajax

    $(document).ready(function () {
       var GetEntityParam = { "ProductName": "YaGao", "ProductCode": "JX80869", "ProductPrice": 40.5};
          $("#FindProdcutDetail").click(function () {
            $.ajax({
                     type: "Get",
                     url: "/api/Default/ProductDetails",
                     data: GetEntityParam
                   })
               })
          })

    result

    7.2  系列化与反系列化传递实体

    ajax

    $(document).ready(function () {
       $("#FindProdcutDetail").click(function () {
           $.ajax({
                    type: "Get",
                    url: "/api/Default/ProductDetails",
                    data: { "productDetail": JSON.stringify({ "ProductName": "YaGao", "ProductCode": "JX80869", "ProductPrice": 40.5 }) }
                 })
             })
         })

     result

    8  小结


     (1)Get参数传递的本质是url字符串拼接;

     (2)url字符串长度受限制;

     (3)Get参数传递在Http请求头部传递,而不支持Request-Body传递;

     (4)Get类型的方法支持参数为基本类型,不支持实体类型;

     (5)Get类型的方法命名,应尽量采用“Get+方法名”的命名方式,且习惯性地在方法前加上[HttpGet特性];

     (6)实参与形参的匹配,遵循路由规则;

    (7)Get对应DB的Select操作,从这一点来理解,就知道为什么Http不支持实体对象传递的合理性了,因为一般情况,我们都是通过简单的字段查询信息(对应基本类型),

    如ID号,用户名等,而不会通过一个实体查询数据;

     三    Post 

    1  基本数据类型传递


     

    1.1  [FromBody]单个参数传递

    ajax

    result

    1.2 dynamic单个参数传递

     ajax

    $(document).ready(function () {
       $("#FindProdcutDetail").click(function () {
          $.ajax({
                   type: "Post",
                   contentType: 'application/json',
                   url: "/api/Default/PostParamToProducts",
                   data: JSON.stringify({"ProductCode":"JX00039"})
               })
           })
       })

    result

    Googel Chrome查看

    2 实体作为参数传递


     ajax

    $(document).ready(function () {
       $("#FindProdcutDetail").click(function () {
          $.ajax({
                   type: "Post",
                   url: "/api/Default/PostParamToProducts",
                   data: { "ProductCode": "JX00036","ProductName":"YaGao","ProductPrice":20.5}
                })
            })
        })

    result

    我们用Googel  Chrome看看

    3 实体集合作为参数传递


     ajax

    $(document).ready(function () {
       var list_ProductDetail = [
           { "ProductCode": "JX00031", "ProductName": "ToothPaste", "ProductPrice": "20.5" },
           { "ProductCode": "JX00032", "ProductName": "ToothBrush ", "ProductPrice": "18.9" },
           { "ProductCode": "JX00033", "ProductName": "Pen", "ProductPrice": "199.9" },
           { "ProductCode": "JX00034", "ProductName": "computer", "ProductPrice": "15000.5" }
           ]
       $("#FindProdcutDetail").click(function () {
       $.ajax({
                 type: "Post",
                 contentType: 'application/json',
                 url: "/api/Default/PostParamToProducts",
                  data: JSON.stringify(list_ProductDetail)
              })
          })
      })

     result

    Google Chrome 查看

    4  数组作为参数传递


     ajax

    $(document).ready(function () {
       var arr = ["a", "b", "c", "d"];
       $("#FindProdcutDetail").click(function () {
          $.ajax({
                   type: "Post",
                   contentType: 'application/json',
                   url: "/api/Default/PostParamToProducts",
                   data: JSON.stringify(arr)
                })
           })
      })

    Result

    我们用Google Chrome看看

    5  小结


     (1)Post参数传递本事是在Request-Body内传递,而Get参数传递本质是url拼接;

    (2)Post参数传递不是key/value形式,而Get参数是key/value形式;

    (3)Post传递参数时,无论是单个参数还是对象,均借助[FromBody]特性(当然,某些情况去掉[FromBody]特性也可把值传递进去,但未了规范化,尽量加上该特性);

    (4)Post没长度限制,而Get有长度限制(一般为1024b);

    (5)Post相对Get,较安全;

    (6)Post操作相当于DB的Insert操作;

    四  总结

    1.虽然HTTP请求方法有20多种,常用的大致为4种,即Get,Post,Put,Delete(当然,像Trace,Head等也常用);

    2.Get,Post,Put,Delete分别对应DB的Select,Insert,Update和Delete操作;

    3.WebApi参数类型,大致分为基本数据类类型和对象数据类型(当然你也可以理解为抽象数据类型);

    4.研究WebApi参数传递,只需研究Get和Post即可,因为其他http方法参数传递基本都是有这两种组合而成(如Put有Get和Post组合而成),或者相似(如Delete与Get相似);

    5.对于控制器方法,尽量参照规范格式写,如在相应控制器方法上加上对应的htt请求(Get对应[HttpGet],Post对应[HttpPost]),方法名尽量采用“Http请类型+方法名”格式(如Get请求,建议采用Get+MethodName;Post请求对应Post+MethodName);

    6.WebApi参数请求,大致分为两大类型,即Request-url和Request-body;

    7.文中我们还简要分析了Get和Post区别;

    8.关于如何设计一个良好的接口,在文章中,我们触及了一下,但未研究,会在后续的文章中单独分析;

    五   服务区

     有喜欢的朋友,可以看一下,不喜欢的的朋友,勿喷,谢谢!!

     

    六   版权区

    • 感谢您的阅读,若有不足之处,欢迎指教,共同学习、共同进步。
    • 博主网址:http://www.cnblogs.com/wangjiming/。
    • 极少部分文章利用读书、参考、引用、抄袭、复制和粘贴等多种方式整合而成的,大部分为原创。
    • 如您喜欢,麻烦推荐一下;如您有新想法,欢迎提出,邮箱:2098469527@qq.com。
    • 可以转载该博客,但必须著名博客来源。
  • 相关阅读:
    Eclipse常用插件推荐
    Open Source Search Engines in Java
    Java: convert a file to a byte array, then convert byte array to a file.
    常用的Eclipse插件介绍
    一个搜索引擎周边的blog
    java文件读取。(单字节读取和按行读取读取)
    im4java
    csv格式读取通用类
    java以流方式下载文件struts2.x版_心灵的港湾_百度空间
    Jetty/Feature/Jetty Maven Plugin
  • 原文地址:https://www.cnblogs.com/wangjiming/p/8378108.html
Copyright © 2011-2022 走看看