buguge - Keep it simple,stupid

知识就是力量,但更重要的,是运用知识的能力why buguge?

导航

浅析Web API中FromBody属性

比较如下两段代码及测试结果:

public class ValuesController : ApiController
{
    // POST api/<controller>
    public string Post(string value)
    {
        return value;
    }
}

 用swagger ui请求时,value的值为“1”或“a“均可返回。

 

public class ValuesController : ApiController
{
    // POST api/<controller>
    public string Post([FromBody]string value)
    {
        return value;
    }
}

用swagger ui请求时,value的值为“1”可正确返回,但为“a”时返回值为null。

 


怎么回事?
显然有必要了解一下FromBody特性,见如下mscor描述。通俗点说,FromBodyAttribute要求被其修饰的参数,必须是序列化后的实体成员。
显然“a”不是序列化后的json串,而“"a"”才是。
那么,“1”与“"1"”为什么都可以呢?这是一个技术细节,我们知道,在一个实体里如果定义了数值类型的属性,则在将这个实体的对象序列化后,它的这些数值参数默认是带双引号的。而实际上,将这些数值参数的双引号去掉,同样是一个有效的json串。所以,不难理解,“1”与“"1"”是等效的json串。

#region 程序集 System.Web.Http.dll, v4.0.0.0
// D:\SourceProject\yi+.gateway\branches\trunkOLd\packages\Microsoft.AspNet.WebApi.Core.4.0.30506.0\lib\net40\System.Web.Http.dll
#endregion

using System;
using System.Web.Http.Controllers;

namespace System.Web.Http
{
    // 摘要: 
    //     一个特性,该特性指定操作参数仅来自传入 System.Net.Http.HttpRequestMessage 的实体正文。
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
    public sealed class FromBodyAttribute : ParameterBindingAttribute
    {
        // 摘要: 
        //     初始化 System.Web.Http.FromBodyAttribute 类的新实例。
        public FromBodyAttribute();

        // 摘要: 
        //     获取参数绑定。
        //
        // 参数: 
        //   parameter:
        //     参数说明。
        //
        // 返回结果: 
        //     参数绑定。
        public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter);
    }
}

 

 

 


最后,贴上两种情况下swagger ui的页面请求截图:

通过比较可以看到,两者的请求参数类型、curl和Request URL是有区别的:
【value参数无FromBody特性的】
value的Type是:query
Curl:curl -X POST --header 'Accept: application/json' 'http://localhost:36024/api/Values?value=a'
Request URL:http://localhost:36024/api/Values?value=a
【value参数有FromBody特性的】
value的Type是:body。这时需要选择Parameter content type,默认是application/json
Curl:curl -X POST --header 'Content-Type: application/json' --header 'Accept: text/json' -d 'a' 'http://localhost:36024/api/Values'
Request URL:http://localhost:36024/api/Values

webapi默认返回的是json格式的字符串。从swagger ui的响应域的标签“Response Body”(不是Response Value)可以看出来,为swagger的细节点赞!

posted on 2017-03-13 21:00  buguge  阅读(2571)  评论(0编辑  收藏  举报