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无疑是一个非常有效的超媒体类型。祝大家龙年新春愉快,吉祥如意!

相关文章:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小勇DW3

Spring的原理性总结

Bean的生命过程可以借鉴Servlet的生命过程,了解其生命过程对于不管是思想还是以后的使用都很有帮助;

1.5K5
来自专栏乐沙弥的世界

使用 runcluvfy 校验Oracle RAC安装环境

--*****************************************

1022
来自专栏Android 研究

Android系统启动——4 zyogte进程 (C篇)

我们大家都是知道"一鼎三足"和"三角形的稳定性",那么支撑Android系统的三个"足"是什么?即init进程、SystemServer进程和Zygote进程。...

2361
来自专栏WindCoder

Spring Boot REST API错误处理指南

本来是5号来的文章,无奈最近准备换工作,一直拖着没写,今天搜索偶然看见有人已经翻译完了,由于时间原因这次就直接转载下吧,现附上英文原文及相关信息,最后再附上译文...

1652
来自专栏SDNLAB

OpenDaylight Carbon二次开发实用指南

通过本文你将知道: Maven Archetype的基本原理以及如何使用Maven Archetype生成适用于不同版本的ODL子项目。 本文将着重讲解cli命...

43215
来自专栏蔡鹏的专栏

Dubbo API形式 简单入门

3553
来自专栏Kubernetes

Kubernetes Job Controller源码分析

Author: xidianwangtao@gmail.com 实现流程图 废话不多说,先把完整流程贴出来。 ? New JobController ty...

7408
来自专栏玩转JavaEE

SpringMVC常用配置

按:最近公众号文章主要是整理一些老文章,主要是个人CSDN上的博客,也会穿插一些新的技术点。 ---- 关于Spring、SpringMVC我们前面几篇博客都介...

2926
来自专栏代码拾遗

深入理解Spring MVC

使用Spring Boot和web,thymeleaf的starter来设置初始工程。xml配置如下:

1042
来自专栏阿杜的世界

Spring Boot Error Response

在昨天的文章最后,我提到一个问题,就是我的例子对错误处理的设计不够。按照RESTful的设计,既然请求是借助HTTP的方法,那么返回信息也应该借助HTTP的状态...

741

扫码关注云+社区