WebApi中的参数传递

WebApi参数传递总结

在WebAPI中,请求主体(HttpContent)只能被读取一次,不被缓存,只能向前读取的流。

举例子说明:

1. 请求地址:/?id=123&name=bob 

    服务端方法: void Action(int id, string name) // 所有参数都是简单类型,因而都将来自url

2. 请求地址:/?id=123&name=bob 

    服务端方法: void Action([FromUri] int id, [FromUri] string name) // 同上

                      void Action([FromBody] string name); //[FormBody]特性显示标明读取整个body为一个字符串作为参数

3. 请求地址: /?id=123 

    类定义:

public class Customer {   // 定义的一个复杂对象类型 
  public string Name { get; set; } 
  public int Age { get; set; } 
}

    服务端方法: void Action(int id, Customer c) // 参数id从query string中读取,参数c是一个复杂Customer对象类戏,通过formatter从body中读取

    服务端方法: void Action(Customer c1, Customer c2) // 出错!多个参数都是复杂类型,都试图从body中读取,而body只能被读取一次

    服务端方法: void Action([FromUri] Customer c1, Customer c2) // 可以!不同于上面的action,复杂类型c1将从url中读取,c2将从body中读取

4.ModelBinder方式:

void Action([ModelBinder(MyCustomBinder)] SomeType c) // 标示使用特定的model binder来解析参数

[ModelBinder(MyCustomBinder)] public class SomeType { } // 通过给特定类型SomeType声明标注[ModelBidner(MyCustomBinder)]特性使得所有SomeType类型参数应用此规则 

void Action(SomeType c) // 由于c的类型为SomeType,因而应用SomeType上的特性决定其采用model binding

总结:

1. 默认简单参数都通过URL参数方式传递,例外:

1.1 如果路由中包含了Id参数,则id参数通过路由方式传递;

1.2 如果参数被标记为[FromBody],则可以该参数可以为简单参数,客户端通过POST方式传递:$.ajax(url, '=value'),或者$.ajax({url: url, data: {'': 'value'}});

2. 默认复杂参数(自定义实体类)都通过POST方式传递,例外:

2.1 如果参数值被标记为[FromUri], 则该参数可以为复杂参数;

3. 被标记为[FromBody]的参数只允许出现一次, 被标记为[FromUri]的参数可以出现多次,如果被标记为[FromUri]的参数是简单参数,该标记可以去掉。

在客户端调用WebApi的一些接口时,最常使用到的HTTP方式有Get, Post, Put, Delete四个,下面会将这四个分成两类进行说明

第一类:Get/Delete

Delete在Body中传递参数有争议, 因此强烈建议只在URL中传递参数,所以这个分类里面只考虑通过URL传递参数的情况。

在URL中可以传递多个参数,但总长度有URL长度限制,参数之间使用&分隔,如以下格式:http://localhost:12345/api/Echo?arg1=value1&arg2=value2&arg3=中文,其中的中文等特殊字符需要使用urlencode进行转义,在WebApi中接收的参数可以是多个单独的参数,也可以是由多个参数封装的对象(这个转换会由框架自动完成)
例如:
http://localhost:12345/api/Echo/Single?arg1=1&arg2=2

http://localhost:12345/api/Echo/Multiple?arg1=1&arg2=2&strArg1=hello&strArg2=world

[RoutePrefix("api/Echo")]  
public class EchoController : ApiController
{
    [Route("Single")]
    public void Get2([FromUri]int arg1, [FromUri]int arg2)
    { }
    [Route("Muliple")]
    public void Get3([FromUri]int arg1, [FromUri]int arg2, [FromUri]Arg arg3)
    { }
}
public class Arg
{
    public string strArg1 { get; set; }
    public string strArg2 { get; set; }
} 

第二类:Post/Put

Post和Put在参数传递时既可以在URL中传递,也可以在Body中传递,当然一起传也是可以的,URL传递符合上面所描述的情况,下面着重说一下在Body中传值的情况。
Body正文只接收一个参数的传递,但不限该参数是一个值还是一个对象,所以如果想要在Body中传递多个参数,需要将这多个参数封装成一个对象

一个值参数

Api中定义的接收方式(还有多种接收参数的方式,这里只是用这一种方式进行举例):

[Route("Single")]
public void Post1([FromBody]int arg1)
{
}

Body中的正文:

1

多个值参数

Api中定义的接收方式:

[Route("Single")]
public void Post1([FromBody]int arg1, [FromBody]int arg2)
{
}

Body中的正文(以json格式为例):

{
    "arg1":1,"arg2":2
}

此种方式会导致服务器报500错误,因为服务器端不能正确解析所传参数

对象参数:

Api中定义的接收方式:

[Route("SingleObject")]
public void Post2([FromBody]Arg arg)
{
}

Body中正文内容(以json为例,若要以form方式传输,请参考form格式):

{
    "strArg1":"hello", "strArg2":"world"
}

若有多传的值会被自动忽略掉

Body正文格式

Body正文格式中分json和form两种传递方式,若使用form方式传递,请将http头Content-Type设置为application/x-www-form-urlencoded, 其中的x-www-form-urlencoded为正文指定编码方式,而使用json形式传递, 请将http头Content-Type设置为application/json; charset=utf-8,参数正文不需要使用特殊的编码处理,不过强烈建议使用json这种传输方式,下面是两个分别使用form和json传递的http包:

Form方式

POST /api/test HTTP/1.1
Connection: keep-alive
Content-Length: 35
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Host: localhost:12345
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36

arg1=1&arg2=2&content=%E6%B5%8B%E8%AF%95

Json方式

POST /api/test HTTP/1.1
Connection: keep-alive
Content-Length: 35
Content-Type: application/json; charset=UTF-8
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Host: localhost:12345
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36

{
    "arg1":1,
    "arg2":2,
    "content":"测试"
}

引用

  1. WebApi参数传递总结

猜你喜欢

转载自blog.csdn.net/weixin_39885843/article/details/88354575