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 請求/響應和媒體類型格式化扮演的角色:

MediaTypeFormatterProcess

這個例子我們使用入門:構建簡單的Web API 的代碼和WCF Web API Preview 6。使用的媒體類型是application/x-protobuf ,REST服務的核心原則就是服務器和客戶端之間的松耦合性,客戶端需要知道書簽的URI,但不應該知道任何其他的URI的知識,但是客戶端必須知道鏈接關系。

image

下面的代碼是自定義的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無疑是一個非常有效的超媒體類型。祝大家龍年新春愉快,吉祥如意!

相關文章:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM