Channels ▼
RSS

.NET

Working with Protobuf WCF Services


Protocol Buffers are a serialization format, developed by Google, that is fast and easy to use. Frequently referred to as "Protobuf," the technology consists of a language- and platform-neutral, extensible, binary format for fast data exchange that relies on an interface description language, which is compiled to native code. This article explains how to work with Protobuf technology. In addition, I'll show how to pair Protobuf with Windows Communication Foundation (WCF), which is Microsoft’s unified programming model for building service-oriented apps. And I'll demonstrate the benefits of using Protobuf this way.

To work with the code examples listed in this article, you need to have:

  • Visual Studio 2010
  • Protocol Buffers for .NET (Protobuf-net)

You can freely download a copy of Protocol Buffers for .NET. Before we delve deep into implementing Protobuf WCF services in .NET, let's take a quick tour of the basics of Protobuf services: What are they and how are they used.

Protocol Buffers

The idea behing is Protocol Buffers to provide a platform- and language-independent format for exchanging serialized, structured data. Protocol Buffers are lighter and faster to handle than XML or JSON. The other major advantages of Protocol Buffers are:

  • Reduced size of the data packets
  • Platform independence
  • Extensibility

Creating Protobuf Objects in Visual Studio

Note that all protobuf-net classes are stored in files that have .proto extensions. You can store one or more proto classes in a single .proto file. Visual Studio 2008 and 2010 now have support for creating protobuf-net classes through a custom tool. You can find more information on how the tool works.

To integrate protobuf-net with Visual Studio, follow these steps:

  • Copy the ProtoBuf.zip file from (protobuf-net installation directory)\ItemTemplates\csharp\data\1033 into (VS install location - Microsoft Visual Studio 10.0)\Common7\IDE\ItemTemplates\CSharp\Data\1033
  • Open the Visual Studio 2010 Command Prompt in Administrative mode
  • Execute the command "devenv /installvstemplates"

You are now ready to create .proto files from Visual Studio. You can now use the Protocol Buffers template — you'll see it in the list of installed templates in your Visual Studio Add New Item dialog as shown in Figure 1.

Protobuf-net
Figure 1: Creating Protocol Buffer objects in Visual Studio.

Protobuf Messages

To create a Protcol Buffer class (known as a "message" in protobuf), select Add | New Item in the solution explorer window, then select Protocol Buffers from the list of the templates displayed, as in Figure 1.

Here's how a typical protobuf message would look:

package DDJ;
message User 
{
 required int32  UserID = 1;
 required string UserName = 2;
 required string UserEmail = 3;
 required string Password = 4;
 optional string PasswordQuestion = 5;
 optional string PasswordAnswer = 6;
}
<

Notice the use of the required attribute in the User message shown above. This qualifier indicates that the attribute is mandatory. The optional attributes are used to indicate that the property may or may not contain data. When creating protobuf-net data classes, each of the properties of the class should be explicitly numbered and have a proper ordering.

You would use the repeated attribute to indicate that the property can contain a list of objects of the same type. For example: Suppose we need to store a history of a user's passwords. To do this, we would need a list. Refer to the PasswordHistory message as shown below:

package DDJ;
message PasswordHistory {
	required string UserID = 1;
	required string Password = 2;
}

We will now use PasswordHistory as a repeated attribute in the User class as shown here:

package DDJ;
message User
{
 required int32  UserID = 1;
 required string UserName = 2;
 required string UserEmail = 3;
 required string Password = 4;
 optional string PasswordQuestion = 5;
 optional string PasswordAnswer = 6;
 repeated string PasswordHistory = 7;
}

Once you create and use your .proto file in Visual Studio, the protogen compiler automatically generates the code-behind file for your proto message. Here's how a typical automatically generated class looks:

[global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"AuthenticateUserResponse")]
  public partial class AuthenticateUserResponse : global::ProtoBuf.IExtensible
  {
    public AuthenticateUserResponse() {}
    
    private int _StatusCode;
    [global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"StatusCode", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)]
    public int StatusCode
    {
      get { return _StatusCode; }
      set { _StatusCode = value; }
    }

    private string _StatusMessage = "";
    [global::ProtoBuf.ProtoMember(2, IsRequired = false, Name=@"StatusMessage", DataFormat = global::ProtoBuf.DataFormat.Default)]
    [global::System.ComponentModel.DefaultValue("")]
    public string StatusMessage
    {
      get { return _StatusMessage; }
      set { _StatusMessage = value; }
    }
    private bool _IsAuthenticated;
    [global::ProtoBuf.ProtoMember(3, IsRequired = true, Name=@"IsAuthenticated", DataFormat = global::ProtoBuf.DataFormat.Default)]
    public bool IsAuthenticated
    {
      get { return _IsAuthenticated; }
      set { _IsAuthenticated = value; }
    }
    private global::ProtoBuf.IExtension extensionObject;
    global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
      { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); }
  }

Using Protobuf with WCF Services

Now let's discuss how to use Protobuf technology in WCF services. Once you are done creating a complete application and its projects, the Solution Explorer might look similar to Figure 2.

Protobuf-net
Figure 2: The Solution Explorer window.

To use protobuf-net with a WCF service, mark your service contract with the ProtoContract attribute. Here's how a typical Protobuf WCF service contract looks:

[ServiceContract,ProtoBuf.ProtoContract]
    public interface ISimpleContract
    {
        [OperationContract]
        Boolean IsAuthenticatedUser(User userObj);
    }

You can also specify that your WCF service should use protobuf-net in the configuration file; more on this later.

Let's implement a sample application that makes use of Protobuf WCF services. To do this, follow these steps:

  1. Open Visual Studio IDE
  2. Click on File | New | Project
  3. Select WCF Service Application from the list of the project types
  4. Save the WCF Service application project with a name
  5. Create data contract classes for this service
  6. Create a service contract and a service implementation class for this service
  7. Repeat steps 3 and 4 to create another WCF Service application with the same implementation

We'll use the DDJ.Services project shown in Figure 2 for our sample: This is a WCF Service application that makes use of Protobuf technology. The other WCF Service aApplication project (Test.Services) contains the same implementation, but doesn't use Protobuf. I have done this so that we can compare the performance of a Protobuf WCF service against a WCF service that has the same implementation, but doesn't employ Protobuf.

Implementing the Data Contracts

In the DDJ.Services project, I use the following data contract classes:

  • AuthenticateUserRequest
  • AuthenticateUserResponse
  • User

The AuthenticateUserRequest class contains the properties used to authenticate a user. The source for this class is:

/// <summary>
    /// AuthenticateUserRequest data contract
    /// </summary>
    [DataContract]
    [ProtoContract]
    public class AuthenticateUserRequest
    {
        [DataMember(Order = 0)]
        [ProtoMember(1)]
        public Int32 UserID;
        [DataMember(Order = 1)]
        [ProtoMember(2)]
        public String Password;
    }

The AuthenticateUser operation contract returns an instance of the AuthenticateUserResponse class.  The properties of this class include: StatusCode, StatusMessage, and a Boolean property called IsAuthenticated that is set to true or false based on whether the user is authenticated. The AuthenticateUserResponse class follows:

/// <summary>
    /// AuthenticateUserResponse data contract
    /// </summary>
    [DataContract]
    [ProtoContract]
    public class AuthenticateUserResponse
    {
        [DataMember(Order = 0)]
        [ProtoMember(1)]
        public Int32 StatusCode;
        [DataMember(Order = 1)]
        [ProtoMember(2)]
        public String StatusMessage;
        [DataMember(Order = 2)]
        [ProtoMember(3)]
        public Boolean IsAuthenticated;
   )

The User class contains necessary properties relating to the User entity, such as UserID, UserName, and so on. The User class is as follows:

/// <summary>
    /// User data contract
    /// </summary>
    [DataContract]
    [ProtoContract]
    public class User
    {
        [DataMember(Order = 0)]
        [ProtoMember(1)]
        public Int32 UserID;
        [DataMember(Order = 1)]
        [ProtoMember(2)]
        public String UserName;

        [DataMember(Order = 2)]
        [ProtoMember(3)]
        public String UserEmail;

        [DataMember(Order = 3)]
        [ProtoMember(4)]
        public String Password;

        [DataMember(Order = 4)]
        [ProtoMember(5)]
        public String FirstName;

        [DataMember(Order = 5)]
        [ProtoMember(6)]
        public String LastName;
    }

Note the use of the ProtoMember attribute in each of the properties of these classes. Also note the ordering in each of the attributes.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video