ARTICLE

Enumeration in DataContract of WCF

Posted by Dhananjay Kumar Articles | C# Language November 01, 2010
By default Enums are serializable. If we define Enum at service side and use it in Data Contract, it is exposed at the client side.
Reader Level:

By default Enums are serializable. If we define Enum at service side and use it in Data Contract, it is exposed at the client side.

For example, if we have an Enum as below, 

1.gif
 
And we are using it in DataContract as below 

2.gif
 
By default Enum is serialized. 

So, let us see the default behavior of Enum with an example.
  1. Create a DataContract called Product.

    Product.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Runtime.Serialization;

    namespace
    WcfService1
    {
        [DataContract]
        public class Product
        {
            [DataMember]
           public  string ProductName;
            [DataMember]
           public  ProductDeliveryPriority ProductPriority;
        }
       public  enum ProductDeliveryPriority
        {
            Low,
            Normal,
            High,
            Urgent
        }
    }

  2. Create the Service Contract. We are just returning a Product from the service.

    IService1.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;

    namespace
    WcfService1
    {
      [ServiceContract ]
        public  interface IService1
        {
          [OperationContract]
          Product GetProduct();
        }
    }

  3. Implement the service in service definition . 

    Service1.svc.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.ServiceModel.Web;
    using System.Text;

    namespace WcfService1
    {
        public class Service1 : IService1 
        {
            public Product GetProduct()
            {
                Product p = new Product { ProductName = "Pen", ProductPriority = ProductDeliveryPriority.Normal };
                return p;
            }
        }
    }

  4. Define the EndPoint in config file as below. We are exposing the service with basicHttpBinding.

    Web.Config

    <?xml version="1.0"?>
    <configuration>
      <system.web>
        <compilation debug="true" targetFramework="4.0" />
      </system.web>
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior>
              <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
              <serviceMetadata httpGetEnabled="true"/>
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <services>
          <service name ="WcfService1.Service1" >
            <endpoint address ="" binding ="basicHttpBinding" contract ="WcfService1.IService1"/>
            <endpoint address ="mex" binding ="mexHttpBinding" contract ="IMetadataExchange"/>
            <host>
              <baseAddresses>
                <add baseAddress ="http://localhost:8181/Service1.svc"/>
              </baseAddresses>
            </host>
          </service>     
        </services>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
     <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
      </system.webServer>
    </configuration>

  5. Test the service in browser 

    3.gif

  6. Consume the service at the client. Add the service reference at the client side and create the proxy. 

    Program.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using ConsoleApplication1.ServiceReference1;

    namespace
    ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Service1Client proxy = new Service1Client();
                Product p = proxy.GetProduct();
                Console.WriteLine(p.ProductName);
                Console.WriteLine(p.ProductPriority.ToString());
                Console.ReadKey(true);
            }
        }
    }
We added the service reference and namespace.  On running the output we will get is

4.gif
 
Excluding certain ENUM values 

If we want to exclude certain member from ENUM then we need to follow below steps 
  1. Decorate the  Enum with DataContract  attribute 

    5.gif
  2. Decorate the entire member we want to expose to client as EnumMember. Any Enum member not decorated with EnumMember will not be exposed to the client. 

    6.gif
In above Enum definition we are not decorating Normal with EnumMember . and in service we are returning Normal to the client . so when client will try to access normal enum value , it will throw an  error.

So let us modify the Enum as below, 

Modified Enum definition 

[DataContract]
   public  enum ProductDeliveryPriority
    {
       [EnumMember]
       Low,     
        Normal,
       [EnumMember]
        High,
        [EnumMember]
        Urgent
    }

And at the client side while accessing 

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using ConsoleApplication1.ServiceReference1;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Service1Client proxy = new Service1Client();
                Product p = proxy.GetProduct();
                Console.WriteLine(p.ProductName);
                Console.WriteLine(p.ProductPriority.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadKey(true);
        }
    }
}

Output

7.gif
 
We are getting this error at client side because in service we are retuning a Product with ProductPriority normal but normal is not attributed with EnumMember. So it is not exposed on wire or serialized.  

Login to add your contents and source code to this article
post comment
     

Hi, nice post, but be aware that you can run into serious problems if your enumeration does not start with 0 (e.g. [DataContract] public enum ProductDeliveryPriority { [EnumMember] Low = 1, Norma = 4l, [EnumMember] High = 8, [EnumMember] Urgent = 16 } I got some problems with deserialization (a pitty I do not remember the exact exception thrown)...but keep that in mind. Kind regards, Harry

Posted by Harry Feb 17, 2011

Dhananjay. Nice one. Simple and well written steps. Easy to Follow.

Posted by Sivaraman Dhamodaran Nov 01, 2010
COMMENT USING
PREMIUM SPONSORS
DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and add new content to existing PDF documents from within your applications.
SPONSORED BY
  • PDF reports have never been easier to create. With our included WYSIWYG Designer, you can layout your reports, set up your data source and let DynamicPDF ReportWriter do the rest.