WCF RESTful服務(wù)的Google Protocol Buffers超媒體類型
Protocol Buffers 是在一個很理想的結(jié)構(gòu)化數(shù)據(jù)的語言中立的序列化格式。你可以考慮一下XML或JSON,但更輕,更小的協(xié)議緩沖區(qū)。 這種格式的廣應(yīng)用于谷歌不同的系統(tǒng)之間交換數(shù)據(jù)。
由于其結(jié)構(gòu)化數(shù)據(jù)的最佳表現(xiàn),protocol buffers 是一個代表RESTful服務(wù)處理的數(shù)據(jù)很好的選擇。要遵循REST的原則, protocol buffers 應(yīng)作為一個新的超媒體類型的代表。 在當(dāng)前版本(.NET 4) 的Windows通訊基礎(chǔ)(WCF),包含一個新的媒體類型,需要相當(dāng)數(shù)量的努力。 幸運(yùn)的是,新版本的WCF HTTP堆棧,使媒體類型的WCF編程模型的一等公民,大家可以Glenn Block’s 博客去了解更詳細(xì)的內(nèi)容。推薦大家假期可以看下這本書《REST實(shí)戰(zhàn)》http://book.douban.com/subject/6854551/
下面我們來介紹如何使用Google Protocol Buffers,只定義一個超媒體類型 ProtoBufferFormatter:
自定義超媒體類型是通過創(chuàng)建自定義的MediaTypeFormatter,實(shí)現(xiàn)OnWritetoStream() 和 OnReadFromStream() 方法進(jìn)行序列化和反序列化處理。人們經(jīng)常認(rèn)為媒體類型只是在服務(wù)端使用,但是它用來在客戶端控制序列化和反序列化的要求,下圖顯示了一個HTTP 請求/響應(yīng)和媒體類型格式化扮演的角色:
這個例子我們使用入門:構(gòu)建簡單的Web API 的代碼和WCF Web API Preview 6。使用的媒體類型是application/x-protobuf ,REST服務(wù)的核心原則就是服務(wù)器和客戶端之間的松耦合性,客戶端需要知道書簽的URI,但不應(yīng)該知道任何其他的URI的知識,但是客戶端必須知道鏈接關(guān)系。
下面的代碼是自定義的ProtoBufferFormatter,構(gòu)造函數(shù)里指明了支持的媒體類型 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對象。
現(xiàn)在需要給我們的.NET對象加入ProtoBuf 序列化的標(biāo)簽:
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運(yùn)行時的超媒體類型集合里。
using Microsoft.ApplicationServer.Http;
using WcfWebFormat.Formatters;
namespace ContactManager
{
public class ContactManagerConfiguration : HttpConfiguration
{
public ContactManagerConfiguration()
{
this.Formatters.Add(new ProtoBufferFormatter());
}
}
}
修改服務(wù)配置,使用ContactManagerConfiguration:
var config = new ContactManagerConfiguration() { EnableTestClient = true };
routes.Add(new ServiceRoute("api/contacts", new HttpServiceHostFactory() { Configuration = config }, typeof(ContactsApi)));
在客戶端調(diào)用的代碼如下:
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服務(wù)使用中ProtoBuf無疑是一個非常有效的超媒體類型。祝大家龍年新春愉快,吉祥如意!
相關(guān)文章:
- 軟件系統(tǒng)開發(fā)中的數(shù)據(jù)交換協(xié)議
- .net自帶二進(jìn)制序列化,XML序列化和ProtoBuf序列化的壓縮對比
- Android上GTalk以及Push機(jī)制的XMPP數(shù)據(jù)選擇使用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
歡迎大家掃描下面二維碼成為我的客戶,扶你上云



浙公網(wǎng)安備 33010602011771號