zoukankan      html  css  js  c++  java
  • 序列化和模型绑定

    两种内置的序列化器

    Web API为我们内置了两种序列化器,即JSON和XML,具体使用哪一个依请求头中Accept值来决定。Accept用来指定响应内容的格式(也称媒体类型),常见的媒体类型有以下几个,如图。

    image

    1.为什么请求同一个资源,IE和Chrome得到的结果不一样呢?

    默认情况下,请求同一个资源,比如:GET api/contact/searchcontactbyid/001,IE拿到的是JSON,而Chrome 拿到的即是XML,这是为什么呢?

    仔细分析就会发现,是它们的请求头的Accept不一样导致的, Chrome显式指定了application/xml,而IE没有显示指定。

    2.自定义序列化器

    我们也可以自定义一个序列化器加到Web API中,步骤如下。

    ①定义一个序列化器继承MediaTypeFormatter或BufferedMediaTypeFormatter。

    ②将序列化器加入到Web API处理管道中,方法如下图。

    image

    定制序列化

    对于默认的JSON和XML序列化器,我们可以对其行为定制,比如控制哪些字段可以被序列化,日期格式,缩进等等。下面就以JSON序列化器为例来介绍。

    1.忽略字段

    默认情况下,所有的共有字段和属性都会被序列化。如果想忽略其中某个字段,有两种方法可以实现。

    ①方法1,使用JsonIgnore特性,下面代码中字段ProductCode就不会被序列化,如下图。

    image

    ②方法2,除了使用json.net自带的特性外,我们还可以使用内置的方法,命名空间System.Runtime.Serialization下的DataContract和DataMember,如果想忽略某个字段,不给它加DataMember特性就可以。当然,内置方法与JsonIgnore不同的地方在于,DataMember还可以序列化私有成员。

    image

    2.是否缩进

    可以通过指定json.net的formatting选项来决定是否缩进,默认值是None即不缩进,如果要其结果缩进可以指定值为Indented,下图是不缩进和缩进的对比。

    image

    图1:不缩进

    image

    图2:缩进

    模型绑定

    Web API中模型绑定非常类似于MVC,分模型验证和参数绑定两个阶段。

    1.模型验证

    当接受到一个请求时,通常需要对其数据进行验证,验证通过后才进行处理。我们可以使用Web API内置的验证机制来实现,包括数据注解和错误处理。

    ①数据注解

    可以使用命名空间System.ComponentModel.DataAnnotations下的特性来标注,比如我希望模型Contact的FirstName不能为null,加上特性Required即可,如下图。

    image

    ②错误处理

    假设我要往服务端插入一条新记录,客户端发送请求POST api/contact/addcontact,请求的JSON数据如下图。

    image

    服务端action代码如下

    image

    通过调试会发现,模型绑定后FirstName为null,所以ModelState.IsValid返回false,如下图。

    image

    图1:FirstName为null

    image

    图2:服务端返回的内容

    上面我们是在action内部做的验证和错误处理,实际上,我们可以通过创建一个filter,在调用action之前就进行验证和错误处理,步骤如下。

    ①定义filter,如图1

    ②应用filter,有两种方式,一是刚定义的filter实例加到HttpConfiguration.Filters集合中,如图2。二是在Controller或Action上应用特性,如图3。

    image

    图1:定义filter

    image

    图2:将filter加到HttpConfiguration.Filters中

    image

    图3:在Action上应用filter

    2.参数绑定

    默认情况下,有两种类型的绑定参数,简单类型(见备注)和自定义类型。对于简单类型,Web API会从URI(包括querystring和route data)中取值;对于自定义类型,Web API会从请求体(request body)中取值。

    注:简单类型,即常见的string,int,bool,datetime等以及能转换成string的类型。

    ①简单类型绑定

    对于简单类型Web API会从route data或query string中取值,如下图。

    GET api/Contact/SearchContactById/001 //route data

    GET api/Contact/SearchContactById?id=001 //query string

    这两个uri都能映射到这个action:

    image

    ②自定义类型绑定

    对于自定义类型Web API会从request body中取值,示例代码如下。

    Request:

    image

    Action:

    image

    Response:

    收到415的错误,错误信息如下图。

    image

    image

    错误日志已经明确告诉我们是由于没有在request header中指定content-type造成的,这里会引申另一个知识点,Web API中的内容协商。简单来说就是,客户端告诉服务端返回什么格式的数据,然后服务端按客户端的要求返回相应格式数据的过程。通常,客户端会在请求头中指定需要的格式,主要的选项如下。

    a.Accept:可接受的媒体类型,如application/json,application/xml等

    b.Accept-Charset:可接受的字符集,如UTF-8,ISO 8859-1等

    c.Accept-Encoding:可接收的内容编码,如“gzip”。

    d.Accept-Language:优先选用的自然语言,如“en-us”。

    了解了内容协商后,我们知道需要在请求头中指定content-type的值。

    Accept指定response body的格式,而Content-Type指定request body的格式,如果没有指定Accept,则使用Content-Type的格式。

    客户端请求:

    image

    服务端响应:HTTP/1.1 200 OK

    ③定制参数绑定

    我们可以改变Web API默认的参数绑定行为,如果要从URI中读取自定义类型,可以使用特性FromUri,如图1;如果要从request body中读取简单类型,可以使用特性FromBody,如图2。

    image

    图1

    请求URI:GET http://localhost.dev.wingontravel.com/HWARestAPI/api/Contact/SearchContact?id=001&FirstName=san&LastName=zhang

    image

    图2

    请求如下图

    image

    需要注意的是:FromUri可以被标注多次,但是FromBody只能被标注一次。

  • 相关阅读:
    20145304《信息安全系统设计基础》第0周学习总结
    20145304 《Java程序设计》课程总结
    20145304 实验五实验报告
    20145304 第十周学习报告
    20145304 Java第九周学习报告
    20145304 实验四实验报告
    20145304 实验三实验报告
    20145304 Java第八周学习报告
    20145304 Java第七周学习报告
    20145303 《信息安全系统设计基础》第7周学习总结(2)
  • 原文地址:https://www.cnblogs.com/mcgrady/p/4701934.html
Copyright © 2011-2022 走看看