WCF

Cross Origin Resource Sharing with WCF JSON REST Services

February 3, 2015 CSharp, WCF , ,

My KonfDB platform provides a reliable way of configuration management as a service for cross-platform multi-tenant applications. When we refer to cross-platform capabilities, one of the ways to allow clients built using native technologies is by the way of REST services. WCF allows us to host a service and expose multiple endpoints using different protocols. So when KonfDB was in the design phase, I chose WCF as a tech-stack to support multiple endpoints and protocols.

I had written an article REST services with Windows Phone which should be a good starting point to understand WCF-REST services. Now, when you want this service to be accessible from different platforms – web, mobile, or across domains (in particular, Ajax requests) then we need to design few interceptors and behaviours that could allow Cross Origin Resource Sharing (CORS)

For this post, I will use the code from my own KonfDB platform. So those interested can actually visit the GitHub repository and explore more as well.

First, how CORS works

 

CORS works by providing specific instructions (sent from server) to the browsers which the browsers respect. These specific instructions are “additional” HTTP headers which are based on HTTP methods – GET or POST with specific MIME types. When we have HTTP POST method with specific MIME, the browser needs to “preflight” the request. Preflight means that the browser first sends an HTTP OPTIONS request header. Upon approval from the server, browser then sends the actual HTTP request.

So in a nutshell, we need some provision to handle these additional HTTP headers. In this post, we will see how we can change a RESTful service to support CORS.

REST Service Interface

 

A typical non-REST service interface defines methods and decorates them with OperationContract attribute. A REST service requires an additional attribute – one of these WebGet, WebPut or WebInvoke. So in the below example, to support Cross Origin Resource Sharing (CORS), we will decorate the method with attribute WebInvoke and set its Method=”*”

 
[ServiceContract(Namespace = ServiceConstants.Schema, Name = "ICommandService")]
public interface ICommandService : IService
{
        [OperationContract(Name = "Execute")]
        [WebInvoke(Method = "*", ResponseFormat = WebMessageFormat.Json,
            BodyStyle = WebMessageBodyStyle.Bare,
            UriTemplate = "/Execute?cmd={command}&token={token}")]
        ServiceCommandOutput ExecuteCommand(string command, string token);
}

RESTful Behaviour and Endpoint

 

In KonfDB, WCF service is hosting in the Windows Service container. To provide consistent behaviour to bindings and for purpose of future extensibility, I have derived bindings from the native bindings available in .NET framework. So my REST binding looks like,

 

    public class RestBinding : WebHttpBinding
    {
        public RestBinding()
        {
            this.Namespace = ServiceConstants.Schema;
            this.Name = ServiceConstants.ServiceName;
            this.CrossDomainScriptAccessEnabled = true;
        }
    }

 

The important point to note is CrossDomainScriptAccessEnabled is set to true. This is very essential for WCF service to work with CORS – and yes, it is safe!

Defining a CORS Message Inspector and Header

As said in the earlier part of the post, we need a mechanism to intercept the request and add additional HTTP headers to tell the browser that the service does support CORS. Since this functionality is required at an endpoint level, we will define an endpoint behaviour for this. The code for the EnableCorsEndpointBehavior looks like,

 
public class EnableCorsEndpointBehavior : BehaviorExtensionElement, IEndpointBehavior
    {
        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) {        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) { }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {
            var requiredHeaders = new Dictionary();

            requiredHeaders.Add("Access-Control-Allow-Origin", "*");
            requiredHeaders.Add("Access-Control-Request-Method", "POST,GET,PUT,DELETE,OPTIONS");
            requiredHeaders.Add("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");

            var inspector = new CustomHeaderMessageInspector(requiredHeaders);
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
        }

        public void Validate(ServiceEndpoint endpoint) { }

        public override Type BehaviorType
        {
            get { return typeof(EnableCorsEndpointBehavior); }
        }

        protected override object CreateBehavior()
        {
            return new EnableCorsEndpointBehavior();
        }
    }

 

Few important points to note

  • First, here are the headers Access-Control-Allow-Origin=* and Access-Control-Request-Method has OPTIONS set in it. If you want requests only from a particular domain name, you can change the value of Access-Control-Allow-Origin=http://www.mydomain.com and it should work correctly.
  • Second, we have passed these additional headers to a MessageInspector using another class CustomHeaderMessageInspector

The CustomHeaderMessageInspector class, that acts as a DispatchInspector, has the functionality to add these headers to the reply so that the client is aware of CORS. The CustomHeaderMessageInspector class looks like,

internal class CustomHeaderMessageInspector : IDispatchMessageInspector
    {
        private readonly Dictionary _requiredHeaders;
        public CustomHeaderMessageInspector(Dictionary headers)
        {
            _requiredHeaders = headers ?? new Dictionary();
        }

        public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
        {
            return null;
        }

        public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
            var httpHeader = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
            foreach (var item in _requiredHeaders)
            {
                httpHeader.Headers.Add(item.Key, item.Value);
            }
        }
    }

 

Last bit, adding this behaviour to the endpoint. Since the service is self-hosted and there is no WCF configuration file, the code looks like

             
            var serviceEndpoint = host.AddServiceEndpoint(typeof (T), binding.WcfBinding, endpointAddress);
            serviceEndpoint.Behaviors.Add(new WebHttpBehavior());
            serviceEndpoint.Behaviors.Add(new FaultingWebHttpBehavior());
            serviceEndpoint.Behaviors.Add(new EnableCorsEndpointBehavior());
            return serviceEndpoint;

Hosting and Testing this service

Using usual ServiceHost you can host this service and the service should run perfectly. To test this service, you can write a jQuery code

            $('#btnGet').click(function () {
                var requestUrl = 'http://localhost:8882/CommandService/Execute?cmd=someCommand&token=alpha';
                var token = null;
                $.ajax({
                    url: requestUrl,
                    type: "GET",
                    contentType: "application/json; charset=utf-8",
                    success: function (data) {
                        var outputData = $.parseJSON(data.Data);
                        token = outputData.Token;

                        ExecuteOtherRequests(token);
                    },
                    error: function (e) {
                        alert('error:' + JSON.stringify(e));
                    }
                });
            });

If you test this on Chrome with Inspector (F12), the network interaction would appear as shown in the screenshot below,

For a single Ajax request, as expected there is an HTTP OPTIONS request followed by HTTP GET request. If CrossDomainScriptAccessEnabled is not set to true in RestBinding, then we would get a HTTP 403 error – METHOD NOT FOUND.

If we look into the headers of the first request, we see that our WCF service (CustomHeaderMessageInspector) has added additional headers (highlighted) back into the request.

Since the browser got a HTTP Status Code = 200, it initiated the second (actual) request which is a HTTP GET request.

You can view the source code in KonfDB GitHub repository.

Optimizing performance of your WCF Services

February 3, 2014 Visual Studio, WCF , ,

Performance Optimization process starts when you are provided with Non-Functional Requirements such as Availability, Concurrent Users, Scalability and so on.  If you are not provided with NFRs, one tends to ignore them and continues build application using Visual Studio Wizards that generate code recipes.  One tends to ignore them until faced upon a production issue that raises some questions on why a recently development application is poorly designed.  As the experts say, the earlier you detect your issues in a life-cycle of a product the cheaper is it to resolve them.  So its better to be aware of design principles and be cautious of code that can cause significant drop in performance.

When it comes to Windows Communication Foundation (WCF), an architect has to take several design decisions.  This article will outline some of the design decisions an architect/lead has to take when he is designing a WCF service.  The pre-requisite for this article is having preliminary knowledge of WCF.   You can refer to MSDN articles on WCF

The right Binding

 

Choosing the right binding is not difficult.  You can read an article on WCF Bindings in depth on MSDN if you want more information.  If we have to summarize the types and some of the overheads in using them, then it would be

  • Basic binding: The BasicHttpBinding is designed to expose a WCF service as a legacy ASMX web service, so that old clients or cross platform clients can work with the new services hosted either over Intranet/ Internet.   This binding, by default, does not enable any security.  The default message encoding is text/XML.
  • Web Service (WS) binding: The WSHttpBinding class uses HTTP or HTTPS for transport, and is designed to offer a variety of features such as reliability, transactions, and security over the Internet.  This means that if a BasicHttpBinding takes 2 network calls (Request & Response) to complete a request, a WSHttpBinding may take over 5 network calls which makes is slower than BasicHttpBinding.  If your application is consuming the services hosted on the same machine, to achieve scalable performance it is preferred to use IPC Binding instead of WsHttpBinding.
  • Federated WS binding:The WSFederationHttpBinding binding is a specialization of the WS binding, offering support for federated security.
  • Duplex WS binding: The WSDualHttpBinding binding, this is similar to the WS binding except it also supports bidirectional communication from the service to the client.  Reliable sessions are enabled by default.
  • TCP binding: The NetTcpBinding is primarily used for cross-machine communication on the Intranet and supports variety of features, including reliability, transactions, and security, and is optimized for WCF-to-WCF communication – only .NET clients can communicate to .NET services using this binding. This is an ideal replacement of socket-based communication.  To achieve greater performance, try changing the following settings
    • Set the value of serviceThrottling to highest
    • Increase the maxItemsInObjectGraph to 2147483647
    • Increase the values of listenBacklog, maxConnections, and maxBuffer
  • Peer network binding:The NetPeerTcpBinding is used for peer networking as a transport. The peer network-enabled client and services all subscribe to the same grid and broadcast messages to it.
  • IPC binding: The NetNamedPipeBinding class, this uses named pipes as a transport for same-machine communication. It is the most secure binding since it cannot accept calls from outside the machine and it supports a variety of features similar to the TCP binding.  It can be used efficiently for cross product communication.
  • MSMQ binding: The NetMsmqBinding uses MSMQ for transport and is designed to offer support for disconnected queued calls.
  • MSMQ integration binding: The MsmqIntegrationBinding converts WCF messages to and from MSMQ messages, and is designed to interoperate with legacy MSMQ clients.

The right Encoder

Once you have decided on the binding you are going to use, the first level of optimization can be done at the message level.   There are 3 message encoders available out of the box in .NET framework.

  • Text – A default encoder for BasicHttpBinding and WsHttpBinding bindings – it uses Uses a Text-based (UTF-8 by default) XML encoding
  • MTOM – An interoperable format(though less broadly supported then text) that allows for a more optimized transmission of binary blobs, as they don’t get base64 encoded.
  • Binary – A default encoder for NetTcpBinding and NetNamedPipeBinding bindings – it avoids base64 encoding your binary blobs, and also uses a dictionary-based algorithm to avoid data duplication. Binary supports “Session Encoders” that get smarter about data usage over the course of the session (through pattern recognition).

Having said that, the best match for you is decided based on

  • Size of the encoded message – as it is going to be transferred over wire.  A smaller message size with not much of hierarchy in objects would be transmitted best in text/XML format.
  • CPU load – while encoding the messages and also process your operations contracts
  • Simplicity – Messages once converted into binary do not remain readable by naked eyes.  If you do not want to log the messages and want faster transmission, binary is the format to go for
  • Interoperable – MTOM does not ensure 100% interoperability with other non-WCF Services.  If you do not require interoperability, binary is the format to go for

Binary encoder, so far, seems to be the fastest encoder and if you are using NetTcpBinding or NetNamedPipeBinding a binary encoder will do wonders for you!    Why?  Over a period of time, “Session encoders” become smarter (by using dictionary and analysing pattern) and perform optimizations to achieve faster speed.

Final Words – A text encoder converts binary into Base64 format which is an overhead (around 4-5 times) and can be avoided by using binary or MTOM encoders.  If there is no binary data in the message, MTOM encoder seems to slower down the performance as it has an overhead of converting the message into MIME format.  So try out different message encoders to check what suits your requirement!

The right Compression

 

Choosing a right encoder can reduce the message size by 4-5 times.  But what if the message size is still in MBs?  There are ways to compress your message and make it compact.  If your WCF Services are hosted on IIS or WAS (Windows Server 2008/2012), you can opt for IIS Compression.  IIS Compression enables you to perform compression on all outgoing/incoming messages using GZip compression.  To enable IIS Configuration, you need to follow steps mentioned by Scot Hanselman’s  article – Enabling dynamic compression (gzip, deflate) for WCF Data Feeds, OData and other custom services in IIS7

Data Caching

 

Caching any data on which your service depends avoids dependency issues and gets you faster access to same data.  There are several frameworks available to cache your data.  If your application is smaller (non-clustered, non-scalable, etc) and your service is not-stateless (you might want to make it stateless), you might want to consider In-Memory caching; however, with large scale applications you might want to check out AppFabric, Coherence, etc.

  • In-memory Caching –  If your WCF services are hosted on IIS or in WAS you can enable ASP.NET Caching by adding AspNetCompatibilityRequirements attribute to your service and setting aspNetCompatibilityEnabled to true in Web.Config file to use ASP.NET Caching block.   If you are using self-hosted applications, you can use Enterprise Library Caching block.  If your application is built on .NET 4.0 or later, you can use Runtime Caching
  • AppFabric – Use AppFabric for dedicated and distributed caching to increase the service performance.  This will help you overcome several problems of in-memory caching such as sticky sessions, caching in each component/service on a server,  synchronization of cache when any data changes and alike.

When storing objects in cache, prefer caching serializable objects.  It can help you to switch caching providers at any time.

Load Balance

 

Load balance should not just be seen as a means to achieve scalability.  While it definitely increases scalability, many times an increased performance is a driving force towards load balancing services.   There is an excellent article on MSDN on Load Balancing WCF services

Accelerated using GPU

 

There are many open-source GPU APIs available out there that can enhance the performance of high data computational tasks or image processing.  Data computation tasks also involve data sorting, filtering and selection – operations that we do using LINQ or PLINQ.  In one of my projects, we observed that operations that took 20,000 milli-seconds on a i5 processor using PLINQ barely took 900 milli-seconds on the same processor using GPU.  So leveraging the power of GPU in your Data-layer based WCF Services can boost the performance of your application by at least 500 times!

Some of the APIs that I recommend are Accelerator by Microsoft and CUDA by NVIDIA.  Both of them support development in C# language.

Conclusion

 

With the right binding and encoder you can expect a 10% increase in the performance but when bundled up with data caching and GPU acceleration, the performance can shoot by a minimum 110%.  So if you are facing issues with optimizing the performance of your WCF service, experiment with the above steps and get started.  Some links that may interest you are,

Let me know if you need any other information on WCF

WCF NetTcp Port Sharing on Windows 8+

October 21, 2013 CSharp, Visual Studio, WCF , ,

In Windows 8, when hosting WCF in a managed application running under a normal user privileges and NetTcp binding, you might get an exception

Verify that the current user is granted access in the appropriate allowAccounts section of SMSvcHost.exe.config

This is due to enhanced security in Windows 7+ operating systems. 

There are 3 ways to get away with this exception

Run as Administrator

Please note that this problem occurs only when you are running a WCF service using a user account.  If you run the service using a Local System, Network Service, Local Service or Administrator, there will be no issues at all.

When running the application as an Administrator, NetTcp Port Sharing service assumes that you are authenticated and can run the service and share data on the TCP layer.

However, if you do not have admin rights you can take the next approach

Downgrade your NET.TCP Port Sharing service

Now this problem occurs for .NET 4.0 framework that upgraded the NET.TCP Port Sharing.  So if you have installed .NET 4.0, you will face this issue.

The easiest way is to change some registry configuration to use v3.0

Key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\NetTcpPortSharing

New Value:
C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\SMSvcHost.exe

When you try to compare the configuration files SMSvcHost.exe.config in v3.0 and v4.0.30319, you will not find any changes that would stop port sharing so I believe, it is the way SMSvcHost works that has made the changes

Grant port sharing rights to yourself

This process is a lengthy process so if you follow through these steps accurately you can get away with this error

  • Visit http://technet.microsoft.com/en-us/sysinternals/bb897417 and download the  PsTool.  We are interested in PsGetSid that gives you unique security identifier for a user or a group.  So if you are targeting this single user, you should be interested in getting SID of a user; otherwise, you can request for a group having all your target audience.  Run PsGetSid <username> to your SID
  • Open the SMSvcHost.exe.config (of .NET 4.0 version, usually in C:\Windows\Microsoft.NET\Framework\v4.0.30319 folder)
  • You will require to use Admin rights to open this config file.  The best way is to open Command Prompt (Run As Administrator) and then type

    notepad C:\Windows\Microsoft.NET\Framework\v4.0.30319\SMSvcHost.exe.config

  • The configuration file has a section called system.serviceModel.activation and a sub-section net.tcp.  This section has security identifiers of LocalSystem, LocalService, NetworkService and Administrators.  We need to add your SID in this configuration file
  • Without changing anything else, add following line in the configuration file (just next to the LocalSystem account

<add securityidentifier="your-SID-that-starts-with-S">

Restart the Net.Tcp Port Sharing service and you should be good to go.

HTTP/S WCF : Commonly faced access issues and solutions

September 5, 2013 CSharp, Visual Studio, WCF , , , ,

When running WCF services on Windows 7+ (actually, includes Vista too) operating systems when you write a simple code at the service side to open the service host, most users experience this issue

HTTP could not register URL http://+:8010/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details).

When you visit the link in the above error, you do not necessarily get the required information to solve this issue quickly.  So let’s see the solution to this commonly faced problem.   HTTP/S services are usually hosted on IIS or self-hosted in an application.   When registering this service on an operating system that has enhanced security (Win7+, Win 2008/2012) you need to perform some administration work such as mentioned below.   Some of you may get several other issues like endpoint not found, or SSL certificate issues. 

This article explains what is required to fix these issues

 

Namespace registration

Namespace registration grants access rights to a specific URL to a specified group/user on a domain or computer.   This one time activity ensures that only authorized users can open up endpoints on a computer/server – this is definitely more secure.

How to authorize your service/user account:

Local user account:

netsh http add urlacl url=http://+:8010/ user=ComputerName\Username

Domain user account:

netsh http add urlacl url=http://+:8010/ user=DomainName\Username

Built-in Network Service account

netsh http add urlacl url=http://+:8010/ user="NT AUTHORITY\NETWORK SERVICE"

Most likely this should directly solve your problem “HTTP could not register URL”  but I would advise going through the other steps on a production machine (actually, any restricted environment) to ensure that there are no hiccups.

 

Firewall Exception

Most organizations have Firewall Restrictions on HTTP communication on Production machines.  In that case, you would have to ensure that the port on which you are doing communication is added to the Firewall Exception list

 

SSL Certificate Store

 

HTTPS services rely on certificate exchange between server and client (in case of mutual authentication) to authenticate the the request and also to encrypt the request data.  These certificates are stored in a certificate store and it is important to configure the certificate access to a port

You can use following command to bind SSL certificate to a port (8010)

httpcfg set ssl -i 0.0.0.0:8010 –h thumprint-of-certificate-in-certificate-store

The thumbprint of a certificate can be retrieved by viewing the certificate properties in Certificate Management Console (mmc)

 

Changing these settings should help you resolve all service access issues

Presentation: 5-steps to Optimizing WCF Services

February 19, 2013 CSharp, Visual Studio, WCF , , ,

[slideshare id=16622012&doc=5-stepstooptimizingwcfservices-130219063219-phpapp02]

Performance oriented Xml and JSON serialization in .NET

November 16, 2011 CSharp, Visual Studio, WCF , , , ,

Microsoft .NET framework provides multiple out-of-the-box data serializers for data transformations.  The most famous one used since .NET 1.0 version is XmlSerializer, while one that has got more famous since .NET 3.0 framework is DataContractSerializer.   But they are not the only two serializers the framework offers.  So in this essay, let’s see the different serializers .NET framework offers and how they are different from each other.  So here’s the list of serializers

  • XmlSerializer: The most commonly used xml serializer
  • JavaScriptSerializer:  Introduced in ASP.NET Ajax Extensions in .NET 2.0, and now marked as obsolete, primarily provided JSON serializer
  • DataContractSerializer: Introduced in .NET 3.0 with Windows Communication Foundation (WCF), this is default serializer in WCF.
  • NetDataContractSerializer: A not-too-famous serializer that includes CLR type information in serialized xml which DataContractSerializer does not.
  • DataContractJsonSerializer:  Introduced in .NET 3.5, this class is handy in generating JSON output of an entity

Next, let’s define a class Employee and implement a serializer class and try out XmlSerializer, DataContractSerializer, NetDataContractSerializer and DataContractJsonSerializer with examples.

Step 1- Defining Employee class

The structure of Employee class is different for different serializers.  So make a note that XmlSerializer requires a parameterless or a default constructor, while other serializers do not require so.  Other serialisers based on DataContractSerializer require DataContract and DataMember attribute on the class and its members, while XmlSerializer requires either a native type, or ISerizable implemented complex class (read: class)

Employee Class
  1. ///<summary>
  2. /// Employee class for all other serializers
  3. ///</summary>
  4. [DataContract]
  5. public class Employee
  6. {
  7.     [DataMember]
  8.     public string Name { get; set; }
  9.     [DataMember]
  10.     public int EmployeeId { get; set; }
  11.     ///<summary>
  12.     /// Note: Default constructor is not mandatory
  13.     ///</summary>
  14.     public Employee(string name, int employeeId)
  15.     {
  16.         this.Name = name;
  17.         this.EmployeeId = employeeId;
  18.     }
  19. }
  20. ///<summary>
  21. /// Employee class for XmlSerializer
  22. ///</summary>
  23. public class Employee
  24. {
  25.     public string Name { get; set; }
  26.     public int EmployeeId { get; set; }
  27.     ///<summary>
  28.     /// Parameter-less constructor is mandatory
  29.     ///</summary>
  30.     public Employee() { }
  31.     public Employee(string name, int employeeId)
  32.     {
  33.         this.Name = name;
  34.         this.EmployeeId = employeeId;
  35.     }
  36. }

Step 2 – Defining the Serialization Factory

To define the serialization factory, we will define an enum SerializerType, and a factory class SerializerFactory and add reference to System.Runtime.Serialization using “Add Reference” option

SerializerType
  1. public enum SerializerType
  2.     {
  3.         ///<summary>
  4.         /// XmlSerializer
  5.         ///</summary>
  6.         Xml,
  7.         ///<summary>
  8.         /// DataContractJsonSerializer
  9.         ///</summary>
  10.         JSON,
  11.         ///<summary>
  12.         /// DataContractSerializer
  13.         ///</summary>
  14.         WCF,
  15.         ///<summary>
  16.         /// NetDataContractSerializer
  17.         ///</summary>
  18.         CLR
  19.     }

The factory class could be plain vanilla object creation based on the enum (SerializerType) value, however creation of serialization object is heavy on performance. Hence, we would like to cache it in the memory for re-use.  So the factory class has been optimized for better performance using a Dictionary of serializers.

Serialization Factory
  1. public static class SerializerFactory
  2.     {
  3.         private static Dictionary<Type, Dictionary<SerializerType, object>> _knownObjects;
  4.         static SerializerFactory()
  5.         {
  6.             _knownObjects = new Dictionary<Type, Dictionary<SerializerType, object>>();
  7.         }
  8.         internal static ISerializer<T1> Create<T1>(SerializerType serializerType)
  9.         {
  10.             Type type = typeof(T1);
  11.             if (_knownObjects.ContainsKey(type))
  12.             {
  13.                 if (_knownObjects[type].ContainsKey(serializerType))
  14.                     return ((ISerializer<T1>)_knownObjects[type][serializerType]);
  15.             }
  16.             ISerializer<T1> returnValue = null;
  17.             switch (serializerType)
  18.             {
  19.                 case SerializerType.Xml:
  20.                     returnValue = new XmlSerializer<T1>();
  21.                     break;
  22.                 case SerializerType.JSON:
  23.                     returnValue = new JsonSerializer<T1>();
  24.                     break;
  25.                 case SerializerType.WCF:
  26.                     returnValue = new WcfSerializer<T1>();
  27.                     break;
  28.                 case SerializerType.CLR:
  29.                     returnValue = new ClrSerializer<T1>();
  30.                     break;
  31.                 default:
  32.                     throw new NotSupportedException(“Unknown serializer type”);
  33.                     break;
  34.             }
  35.             if (_knownObjects.ContainsKey(type) == false)
  36.                 _knownObjects.Add(type, new Dictionary<SerializerType, object>());
  37.             _knownObjects[type].Add(serializerType, returnValue);
  38.             return returnValue;
  39.         }
  40.     }

 

Step 3 – The Main Program (consuming application)

Our main program should be able to support serialization of Employee class, or a list of employee class as shown below:

Main Program
  1. class Program
  2.     {
  3.         static void Main(string[] args)
  4.         {
  5.             List<Employee> employees = new List<Employee>()
  6.             {
  7.                 new Employee(“Tim”, 1392902),
  8.                 new Employee(“Shawn”, 156902),
  9.             };
  10.             ISerializer<List<Employee>> xmlSerializer = SerializerFactory.Create<List<Employee>>(SerializerType.Xml);
  11.             string xml = xmlSerializer.Serialize(employees);
  12.             ISerializer<List<Employee>> jsonSerializer = SerializerFactory.Create<List<Employee>>(SerializerType.JSON);
  13.             string json = jsonSerializer.Serialize(employees);
  14.             ISerializer<List<Employee>> clrSerializer = SerializerFactory.Create<List<Employee>>(SerializerType.CLR);
  15.             string clr = clrSerializer.Serialize(employees);
  16.             ISerializer<List<Employee>> wcfSerializer = SerializerFactory.Create<List<Employee>>(SerializerType.WCF);
  17.             string wcf = wcfSerializer.Serialize(employees);
  18.             Console.ReadKey();
  19.         }
  20.     }

 

Step 4 – The Serializer implementations

To make this essay shorter and easy to comprehend, only two implementations have been mentioned here: Xml and JSON serializer.  The other two have been included in the source code.

Implementing XmlSerializer

As mentioned earlier, the Xml Serializer requires a default constructor without which the program will throw a runtime exception.

Implementation: XmlSerializer
  1. public class XmlSerializer<T> : ISerializer<T>
  2.     {
  3.         System.Xml.Serialization.XmlSerializer _xmlSerializer =
  4.             new System.Xml.Serialization.XmlSerializer(typeof(T));
  5.         public string Serialize(T value)
  6.         {
  7.             MemoryStream memoryStream = new MemoryStream();
  8.             XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
  9.             _xmlSerializer.Serialize(xmlTextWriter, value);
  10.             memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
  11.             return memoryStream.ToArray().ToStringValue();
  12.         }
  13.         public T Deserialize(string value)
  14.         {
  15.             MemoryStream memoryStream = new MemoryStream(value.ToByteArray());
  16.             XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
  17.             return (T)_xmlSerializer.Deserialize(memoryStream);
  18.         }
  19.     }

 

Implementing JSON Serializer

A Json Serializer is very handy serializer specially when dealing with REST services, or JavaScript, or cross-platform messaging applications.  In recent times, JSON has gained more adoptability considering the ease to understand the serialized output and the cleanliness

Implementation:JSON Serializer
  1. public class JsonSerializer<T> : ISerializer<T>
  2.     {
  3.         DataContractJsonSerializer _jsonSerializer = new DataContractJsonSerializer(typeof(T));
  4.         public string Serialize(T value)
  5.         {
  6.             MemoryStream ms = new MemoryStream();
  7.             _jsonSerializer.WriteObject(ms, value);
  8.             string retVal = ms.ToArray().ToStringValue();
  9.             ms.Dispose();
  10.             return retVal;
  11.         }
  12.         public T Deserialize(string value)
  13.         {
  14.             MemoryStream ms = new MemoryStream(value.ToByteArray());
  15.             T obj = (T)_jsonSerializer.ReadObject(ms);
  16.             ms.Close();
  17.             ms.Dispose();
  18.             return obj;
  19.         }
  20.     }

 

Step 5 – Comparing the serialization results

XmlSerializer

<?xml version=”1.0″ encoding=”utf-8″?>
<ArrayOfEmployee xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”>
<Employee>
<Name>Tim</Name>
<EmployeeId>1392902</EmployeeId>
</Employee>
<Employee>
<Name>Shawn</Name>
<EmployeeId>156902</EmployeeId>
</Employee>
</ArrayOfEmployee>

A default schema/namespace defined by w3.org is added in the root node and the collection is named as ArrayOfEmployee. The output is always a valid Xml.

DataContractJsonSerializer

[
{“EmployeeId”:1392902,”Name”:”Tim”},

{“EmployeeId”:156902,”Name”:”Shawn”}

]

There is no schema added to the serialized string and the string is more clean and readable.  Items are grouped by parenthesis { } and the collection is encapsulated within Box brackets [ ]

DataContractSerializer

<ArrayOfEmployee xmlns=”http://schemas.datacontract.org/2004/07/Serializers” xmlns:i=”http://www.w3.org/2001/XMLSchema-instance”>
<Employee>
<EmployeeId>1392902</EmployeeId>
<Name>Tim</Name>
</Employee>
<Employee>
<EmployeeId>156902</EmployeeId>
<Name>Shawn</Name>
</Employee>
</ArrayOfEmployee>

A default schema/namespace defined by Microsoft and w3.org is added in the root node and the collection is named as ArrayOfEmployee. The output is always a valid Xml.

NetDataContractSerializer

<ArrayOfEmployee z:Id=”1″ z:Type=”System.Collections.Generic.List`1[[Serializers.Employee, Serializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]” z:Assembly=”0″ xmlns=”http://schemas.datacontract.org/2004/07/Serializers” xmlns:i=”http://www.w3.org/2001/XMLSchema-instance” xmlns:z=”http://schemas.microsoft.com/2003/10/Serialization/”>
<_items z:Id=”2″ z:Size=”4″>
<Employee z:Id=”3″>
<EmployeeId>1392902</EmployeeId>
<Name z:Id=”4″>Tim</Name>
</Employee>
<Employee z:Id=”5″>
<EmployeeId>156902</EmployeeId>
<Name z:Id=”6″>Shawn</Name>
</Employee>
<Employee i:nil=”true”/>
<Employee i:nil=”true”/>
</_items>
<_size>2</_size>
<_version>2</_version>
</ArrayOfEmployee>

A default schema/namespace defined by Microsoft and w3.org is added in the root node and the collection is named as ArrayOfEmployee. The output is always a valid Xml, however the Xml nodes also define CLR metadata such as Type, Size, Version, Id, etc.

[Updated] Performance benchmarks

I modified the example to add 200K employees to the collection to benchmark the performance results.  For the first time, serialization took more time as the serialization object was not cached, but for the subsequent times there was 17-44% improvement in the performance.

XmlSerializer (1): Time to executed 1142.0654 mSec
XmlSerializer (2): Time to executed 635.0364 mSec

DataContractJsonSerializer (1): Time to executed 847.0484 mSec
DataContractJsonSerializer (2): Time to executed 611.0349 mSec
CLR (1): Time to executed 2179.1246 mSec
CLR (2): Time to executed 1914.1095 mSec
DataContractSerializer (1): Time to executed 539.0308 mSec
DataContractSerializer (2): Time to executed 413.0236 mSec
What is worth noticing is the that DataContractSerializer is the fastest serializer, followed by DataContractJsonSerializer and XmlSerializer.  Unless absolutely required NetDataContractSerializer should not be used.

I hope this essay helps in understanding serializers better!

Download the source code [serializers.zip] from SkyDrive

WCF Rest Services for Windows Phone

August 14, 2011 CSharp, Visual Studio, WCF, Windows Phone , , ,

So great, to create WCF Rest services for Windows Phone, you have to follow just 5 steps.  This post will have more code than words, making it neat and to-the-point

Step 1: Create a WCF Service

Define the interface IMyService in ‘Services’ folder of YourWebsite

namespace YourWebsite.Services
{
       [ServiceContract(Namespace = "http://YourWebsite.com/services", Name = "MyService")]
       public interface IMyService
       {
         [OperationContract(Name="DoWork")]
         [WebGet(UriTemplate = "?nm={name}",  RequestFormat = WebMessageFormat.Xml, 
                ResponseFormat = WebMessageFormat.Xml,
                BodyStyle = WebMessageBodyStyle.Bare)]
         [FaultContract(typeof(ServiceError))]

         bool DoWork(string name);
       }
}

Add a service MyService.svc that inherits from IMyService

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MyService : IMyService
{
      public bool DoWork(string name)
      {
         return true;
      }
}

Step 2: Modify the markup of MyService.svc

The markup of the MyService.svc should have
Factory=”System.ServiceModel.Activation.WebServiceHostFactory”

<%@ ServiceHost Language="C#" Debug="true" Service="YourWebsite.Services.MyService"
Factory="System.ServiceModel.Activation.WebServiceHostFactory"
CodeBehind="MyService.svc.cs" >

Step 3: Modify Web.Config of the Hosting Website

Add REST behavior (webHttp) to web.config

<system.serviceModel>
  <serviceHostingEnvironment>
    <baseAddressPrefixFilters>
      <add prefix="http://www.YourWebsite.com/Services"/>
    </baseAddressPrefixFilters>
  </serviceHostingEnvironment>
  <behaviors>
    <endpointBehaviors>
      <behavior name="restBehavior">
        <webHttp />
      </behavior>
    </endpointBehaviors>
    <serviceBehaviors>
      <behavior name="">
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="false" />
      </behavior>
    </serviceBehaviors>
  </behaviors>

  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  <client>
    <endpoint address="MyService.svc" binding="webHttpBinding" contract="YourWebsite.Services.IMyService" behaviorConfiguration="restBehavior" />
  </client>

</system.serviceModel>

 

Step 4: Calling MyService in Windows Phone

We don’t need to create any proxy class, and a simple WebClient can do the proxy stuff for us!

string url = string.Format("http://yourwebsite.com/services/MyService.svc?nm={0}", "My Name");
WebClient proxy = new WebClient();
proxy.OpenReadCompleted += new OpenReadCompletedEventHandler(proxy_OpenReadCompleted);
proxy.OpenReadAsync(new Uri(url, UriKind.Absolute));

Once the WCF service is invoked, proxy_OpenReadCompleted is called.

private void proxy_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
      if (e.Error != null)
      {
          // do something
      }

      DataContractSerializer serializer = new DataContractSerializer(typeof(bool));
      bool returnValue = (bool)serializer.ReadObject(e.Result);

}

Step 5: Execute

And you are done!  Just execute your Windows Phone application and you will have the RESTed output 🙂

WCF Binding – which and when?

December 17, 2009 CSharp, Visual Studio, WCF , ,

A question that boggles our mind and makes us think many times. Which binding should be used when? Let’s throw some light on this.

  • Case 1: Interaction with MSMQ
    • Legacy MSMQ : msmqIntegrationBinding
    • No Legacy MSMQ: netMsMqBinding
  • Case 2: Interaction with Peers : netPeerTcpBinding
  • Case 3: Interaction with local services: netNamedPipeBinding
  • Case 4: Interoperability:
    • Basic (with Legacy ASMX service): basicHttpBinding
    • WS* Non Duplex – wsHttpBinding
    • WS* Duplex – wsDualHttpBinding
  • Other cases (no interoperability, no queuing, no peer): netTcpBinding

 Hope this helps!

WCF “k__BackingField” Property Naming

July 20, 2009 CSharp, Visual Studio, WCF , ,

While I was working on a project that involved designing WCF services as Backend layer, I ended up defining a class

[Serializable] public class ProgramDetails
{
   
public string ProgramName { get; set; }
}

When this WCF service is exposed, there is a little different behavior in the naming of this Class and its Members.

When serializing these objects, the serializer will look at all FIELDS of the class no matter their scope:  public, private, etc.  This is because it uses System.Runtime.Serialization, not System.Xml.Serialization.

What happens as a result is – suffix k__BackingField added to each property. That is ProgramName becomes ProgramNamek__BackingField.  This is really annoying to see such cryptic thing. So how do we resolve it?

Its simple!  Modify your code to-

[DataContract]
public class
ProgramDetails
{
       
[DataMember]         public string ProgramName { get; set; }
}

System.Runtime.Serialization, the serializer will interpret your DataMembers as fields on the class and use your naming.  So what you see is ProgramName and not ProgramNamek__BackingField

Follow on Feedly