WCF RESTful服务的Google Protocol Buffers超媒体类型
Protocol Buffers 是在一个很理想的结构化数据的语言中立的序列化格式。你可以考虑一下XML或JSON,但更轻,更小的协议缓冲区。 这种格式的广应用于谷歌不同的系统之间交换数据。
由于其结构化数据的最佳表现,protocol buffers 是一个代表RESTful服务处理的数据很好的选择。要遵循REST的原则, protocol buffers 应作为一个新的超媒体类型的代表。 在当前版本(.NET 4) 的Windows通讯基础(WCF),包含一个新的媒体类型,需要相当数量的努力。 幸运的是,新版本的WCF HTTP堆栈,使媒体类型的WCF编程模型的一等公民,大家可以Glenn Block’s 博客去了解更详细的内容。推荐大家假期可以看下这本书《REST实战》http://book.douban.com/subject/6854551/
下面我们来介绍如何使用Google Protocol Buffers,只定义一个超媒体类型 ProtoBufferFormatter:
自定义超媒体类型是通过创建自定义的MediaTypeFormatter,实现OnWritetoStream() 和 OnReadFromStream() 方法进行序列化和反序列化处理。人们经常认为媒体类型只是在服务端使用,但是它用来在客户端控制序列化和反序列化的要求,下图显示了一个HTTP 请求/响应和媒体类型格式化扮演的角色:
这个例子我们使用入门:构建简单的Web API 的代码和WCF Web API Preview 6。使用的媒体类型是application/x-protobuf ,REST服务的核心原则就是服务器和客户端之间的松耦合性,客户端需要知道书签的URI,但不应该知道任何其他的URI的知识,但是客户端必须知道链接关系。
下面的代码是自定义的ProtoBufferFormatter,构造函数里指明了支持的媒体类型 application/x-protobuf。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net.Http.Formatting;
using System.IO;
using ProtoBuf;
using ProtoBuf.Meta;
namespace WcfWebFormat.Formatters
{
public class ProtoBufferFormatter : MediaTypeFormatter
{
public ProtoBufferFormatter()
{
this.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-protobuf"));
}
protected override void OnWriteToStream(Type type, object value, Stream stream, System.Net.Http.Headers.HttpContentHeaders contentHeaders, System.Net.TransportContext context)
{
Serializer.Serialize(stream, value);
}
protected override object OnReadFromStream(Type type, Stream stream, System.Net.Http.Headers.HttpContentHeaders contentHeaders)
{
object obj = (RuntimeTypeModel.Default).Deserialize(stream, null, type);
return obj;
}
}
}
如上所示,我们在OnWriteToStream方法中将.NET对象序列化为ProtoBuf格式,在OnReadFromStream方法中将ProtoBuf格式饭序列化为.NET对象。
现在需要给我们的.NET对象加入ProtoBuf 序列化的标签:
using System.Collections.Generic;
using System.Xml.Serialization;
using ProtoBuf;
namespace ContactManager.Resources
{
[ProtoContract]
public class Contact
{
[ProtoMember(1)]
public int ContactId { get; set; }
[ProtoMember(2)]
public string Name { get; set; }
}
}
把ProtoBufferFormatter 加入到WCF运行时的超媒体类型集合里。
using Microsoft.ApplicationServer.Http;
using WcfWebFormat.Formatters;
namespace ContactManager
{
public class ContactManagerConfiguration : HttpConfiguration
{
public ContactManagerConfiguration()
{
this.Formatters.Add(new ProtoBufferFormatter());
}
}
}
修改服务配置,使用ContactManagerConfiguration:
var config = new ContactManagerConfiguration() { EnableTestClient = true };
routes.Add(new ServiceRoute("api/contacts", new HttpServiceHostFactory() { Configuration = config }, typeof(ContactsApi)));
在客户端调用的代码如下:
var serviceUri = new Uri("http://localhost:9000/api/contacts/");
var httpClient = new HttpClient();
httpClient.BaseAddress = serviceUri;
httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/x-protobuf"));
var response = httpClient.GetAsync("1").Result;
Contact obj = (RuntimeTypeModel.Default).Deserialize(response.Content.ReadAsStreamAsync().Result, null, typeof(Contact)) as Contact;
var formatters = new MediaTypeFormatterCollection() { new ProtoBufferFormatter() };
var content = new ObjectContent<Contact>(obj, "application/x-protobuf",formatters);
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-protobuf");
httpClient.PostAsync(serviceUri,content);
即使目前来说Google Protocol Buffers没有XML/JSON那样普及,RESTful服务使用中ProtoBuf无疑是一个非常有效的超媒体类型。祝大家龙年新春愉快,吉祥如意!
相关文章:
- 软件系统开发中的数据交换协议
- .net自带二进制序列化,XML序列化和ProtoBuf序列化的压缩对比
- Android上GTalk以及Push机制的XMPP数据选择使用protobuf格式而非XML
- Leverage T4Scaffolding for WCF Web API
- using-protocol-buffers-on-net-platform-part-i
- using-protocol-buffers-on-net-platform-part-ii
- Restful WCF / EF POCO / UnitOfWork / Repository / MEF : 1 of 2
- 几个提高工作效率的Python内置小工具
- J2EE相关总结
- (53) 剖析Collections - 算法 / 计算机程序的思维逻辑
- Flask使用Blueprint进行多模块应用的编写
- 优雅的在终端中编写Python
- Eclipse相关问题
- (54) 剖析Collections - 设计模式 / 计算机程序的思维逻辑
- Django 博客教程(三):创建应用和编写数据库模型
- package-info.java文件详解
- 在Spring下集成ActiveMQ
- Java中只有按值传递,没有按引用传递!
- 我是如何使用Python来自动化我的婚礼的
- left join 过滤条件写在on后面和写在where 后面的区别
- 如何在大量jar包中搜索特定字符
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- python 的topk算法实例
- android使用viewpager计算偏移量实现选项卡功能
- Android画板开发之撤销反撤销功能
- Android实现复制Assets文件到SD卡
- Android画板开发之添加背景和保存画板内容为图片
- 直播插件体系设计
- linux 下selenium chrome使用详解
- WeTest:五年沉淀,打造游戏品质的坚实后盾
- ES5新增方法
- 筛选商品案例
- volatile关键字在Android中到底有什么用?
- Python无头爬虫下载文件的实现
- Python基于stuck实现scoket文件传输
- Python %r和%s区别代码实例解析
- Python基础类继承重写实现原理解析