Don’t Create REST APIs with WCF REST Services…use Web API Instead

There was time when developers used to create Web Service using the WCF. Their argument was using basicHttpBinding makes a WCF service as a Web Service. Yes that ASMX based web service. I never agree to this argument.

image

Clearly WCF was an evolvement over ASMX Web Service. Now let us talk about purpose of this article, that saga of Web API and REST Service. To start with let us understand the background.

REST SERVICE

image

A typical REST Service in WCF would look like as follows:

clip_image002

Point to be noticed here is that while creating the service we are defining the resource type. Since in above service we want to work with both JSON and XML message format, we are creating two services for the same.

EndPoint for REST Service can be created using the factor as shown in the snippet below,

clip_image004

This is the simplest WCF REST Service one could create. We can have different HTTP operations on the same URL. We can perform HTTP GET, POST, PUT, DELETE on the same resource URL in the WCF REST service. However while creating the service, we need to take care of the message format. WCF REST service use the WCF channel and messaging architecture which is used in the WCF SOAP service.

ASP.NET WEB API

This is based on the ASP.NET MVC architecture to create an API for the web. We can create a RESTful API using the ASP.NET Web API. A simple Web API is a class which inherits ApiController class.

clip_image006

Keep in mind that ASP.NET Web APIs does not have the EndPoints and bindings. It utilizes the ASP.NET MVC routings to resolve the resources. Here resource describes their own capabilities and interactions.

To understand difference between REST Service and ASP.NET Web API, let us try to understand The Richardson Maturity Model.

RMM: Richardson Maturity Model classify an API into different levels on the basis of how well they use or take advantage of the web.

image

There are four levels in the RMM from level 0 to level 3.

image

Now we know different levels of RMM, so let us try to map WCF REST Service and the ASP.NET Web API to RMM.

In WCF REST Service

  • Can have multiple URI
  • Can have multiple HTTP methods
  • Operations are defined by the URI
  • Each operation has its own URI
  • Each URI cross ponds to a method on the server.

Let us examine nature of REST Service. Let us assume we want to perform CRUD operation on the BloodDonor table. WCF REST Service allows us to have different methods on the same URI. So it is very much resource oriented. Resource is uniquely identified by the URI and we can have multiple HTTP method on the same resource or URI. A WCF REST Service for CRUD operation may look like as shown in the listing below,

image

Before we conclude that WCF REST Service can be placed in the level 2, there is a catch in it. Above created WCF REST does not know the content negotiation. Client cannot request for a particular type of content and can only work with the XML message format (in this case). WCF REST service cannot negotiate with the resource on the same URI in the multiple message format.

image

Now let us focus on the ASP.NET Web API. It can be also be placed in the level 2 with content negotiation and the support for multiple message format on the same URI.

image

A typical ASP.NET Web API may look as shown in the listing below,

clip_image002[6]

ASP.NET Web API have single URI for multiple operations working on different HTTP methods. However unlikely WCF REST, while accessing ASP.NET Web API, client can negotiate the content. Client can pass the message formant want to work with.

Let us see this in action using the Fiddler. In the fiddler when we pass content type as XML, ASP.NET Web API will return response in XML message format as shown in the image below,

clip_image004[6]

In the fiddler when we pass content type as JSON, ASP.NET Web API will return response in JSON message format as shown in the image below,

clip_image006[6]

Clearly in the ASP.NET Web API client can pass the message format in the request header. Some other characteristics of the ASP.NET Web API over the WCF REST Service is as follows:

  • Unit Testability
  • Support for multiple format
  • Symmetric programming experience at client and server
  • Multiple hosting options

By discussion so far we can say you don’t create REST Service using the Web API. Web API is has more features to put itself in the level 2 of the Richardson Maturity Model.

image I am sure this is a subjective discussion, so would love to read your thought on the same. Feel free to comment your view on my understanding.

Happy coding.

Generics in WCF Data Contract

In my WCF training, I often get questions that can we expose a generic type as DataContract in WCF? Yes, WCF allows us to expose the generic types as Data Contract.

Let us say we have a generic type Foo. We can apply data contract on the Foo as follows:

 


  [DataContract]
    public class Foo<T>
    {
        [DataMember]
        public T fooName { get; set; }
        [DataMember]
        public T fooAge { get; set; }
    }


We can use Foo<T> generic type in operation contract as follows:


        [OperationContract]
        Foo<string> GetFoo();

The service is implemented as follows:


 public Foo<string> GetFoo()
        {
            Foo<string> foo = new Foo<string>();
            foo.fooAge = "32";
            foo.fooName = "dj";
            return foo; 
        }

This is how you can create a service using generic types as Data Contract. However at the client side generic type will be not shown and data contract will be exposed with the name appended by type. So at the client side you will have FooOfString class as shown below:

image

We can consume the service created above as follows:


Service1Client proxy = new Service1Client();         
            FooOfstring foo = proxy.GetFoo();
            Console.WriteLine(foo.fooAge + foo.fooName);
            Console.ReadKey(true);


You will get expected output as shown below:

image

We learnt that the WCF supports exposing a generic type as DataContract.

Happy Coding.

Data Contract Serialization Events in WCF

In WCF we use the DataContract to serialize and deserialize the custom data. Sometime you may come across a scenario do some work before or after the data gets serialized or deserialized. These are following four events provided on the DataContract.

image

You are free to give any method name provided method should return void and takes StreamingContext as input parameter. In a block diagram we can show events sequence as follows:

image

You can create these events inside the class decorated with DataContract. Now let us see some real time examples. Let us say you have a DataContract as follows:

 


[DataContract]
    public class Product
    {
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public double Price { get; set; }
     }
}


We have a very simple ServiceContract defined as follows:

 


[ServiceContract]
    public interface IService1
    {

        [OperationContract]
        Product GetProduct(Product p);
      
    }


Service is implemented as follow which is basically echoing the data provided by the client.

 


public class Service1 : IService1
    {


        public Product GetProduct(Product p)
        {
            Product p1 = new Product { Name = p.Name, Price = p.Price };
            return p1; 
        }
    }


So far great now let is consume the service and examine the sequence of the serialization and deserialization events. Service is consumed as follows

 


Service1Client proxy = new Service1Client();
            Product p = new Product { Price = 300, Name = "Pen" };
            var result = proxy.GetProduct(p);
            Console.WriteLine(result.Name + result.Price);
            Console.ReadKey(true);


Now let us go ahead and modify the data contract class by adding the events. Modified class will look like as follows:

 


using System.Runtime.Serialization;

namespace DataContractEventsDemo
{
    [DataContract]
    public class Product
    {
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public double Price { get; set; }

        [OnSerializing]
        void OnSerializing(StreamingContext context)
        {

        }
        [OnSerialized]
        void OnSerialized(StreamingContext context)
        {

        }
        [OnDeserializing]
        void OnDeserializing(StreamingContext context)
        {

        }
        [OnDeserialized]
        void OnDeserialized(StreamingContext context)
        {

        }
    }
}

To find out sequence in which events get executed put a break point on the events. You will find events get executed in following sequence

image

Now consider a real time scenario that if client is not passing price of the product then service should provide a default price value. You can do that in OnDeserialized event as follows:

 

[OnDeserialized]
        void OnDeserialized(StreamingContext context)
        {
            if(Price==0)
            {
                Price = 99; 
            }
           
        }

Now if modify the client and not provide price as shown below

 


  static void Main(string[] args)
        {

            Service1Client proxy = new Service1Client();
            Product p = new Product { Name = "Pen" };
            var result = proxy.GetProduct(p);
            Console.WriteLine(result.Name + result.Price);
            Console.ReadKey(true);
        }

You will get output with default price as follows

clip_image002These events are useful to provide default values, closing connections to data base etc.Hope you find the post useful. Happy Coding.

Multiple bindings in self-hosted WCF Service

Even though WCF is now, more than 5 years old but still I see developers struggling with the multiple bindings specially when hosted in a managed console application. In this post, step by step we will learn to create a WCF Service with multiple bindings and host the service in a managed console application. We will do the following tasks in this post,

  • Create a service with the netTCPBinding
  • Host the service in a console application
  • Add wsHttpBinding EndPoint in the service
  • Consume the service in a client

To start with create a project by choosing either WCF Service Application or WCF Service Library from the WCF tab. I am selecting WCF Service Library project template.

clip_image002

Let us create a very simple service contract as follows


using System.ServiceModel;

namespace MultipleBindingSelfHosted
{
   
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string GetData(int value);

        
    }

}


Next let us implement the service as follows:


namespace MultipleBindingSelfHosted
{
    public class Service1 : IService1
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

       
    }
}


By this step we have created the service and implemented it. Compile the solution to make sure that everything is fine in the WCF project.

Now let us go ahead and add a console application in the project. This application will be the host application in which the service will be hosted. Let us follow the given steps:

  1. Create a console application in the project
  2. Add reference of System.ServiceModel
  3. Add reference of WCF project

Next in the App.config file of the console application we need to add service’s Endpoint configurations. Let us start with adding netTCPBinding Endpoint. To add the configuration follow the steps shown as follows:

  1. Add system.serviceModel
  2. Add services in the system.servicxeModel
  3. Add host base address in the host section
  4. Add Endpoint with netTcpBinding
  5. Add Metadata Endpoint for netTcpBinding

These steps can be done as shown below:

 

<system.serviceModel>

    <services>
      <service name="MultipleBindingSelfHosted.Service1" behaviorConfiguration="MultipleBindingSelfHostedBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:9002/MultipleBindingSelfHosted"/>
          </baseAddresses>
        </host>
        <endpoint address="net.tcp://localhost:9002/MultipleBindingSelfHosted"
                  binding="netTcpBinding" 
                  contract="MultipleBindingSelfHosted.IService1"/>
        <endpoint address="mex"
                  binding="mexTcpBinding" 
                  contract="IMetadataExchange"/>
      </service>
    </services>

  </system.serviceModel>


If you notice above we have added a service behaviour. So let us go ahead and configure the behaviour as follows:

 

<behaviors>
      <serviceBehaviors>
        <behavior name="MultipleBindingSelfHostedBehavior">
          <serviceMetadata httpGetEnabled="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

Great, by this step we have added Endpoint with the netTcpBinding. Next let us go ahead and create instance of the service host by passing service definition class in the constructor.


using System;
using System.ServiceModel; 

namespace MultipleBindingSelfHosted.Host
{
    class Program
    {
        static void Main(string[] args)
        {

            ServiceHost host = new ServiceHost(typeof(Service1));
            host.Open();
            Console.Write("Service is up and running");
            Console.WriteLine("To stop service press any key !!! ");
            Console.ReadKey();
            host.Close();

        }
    }
}


Press F5 to run the host application. You should see host application running as expected as follows:clip_image002[6]

Next we will go ahead and add an Endpoint for wsHttpBinding. To do this follows the steps as discussed follows:

  1. Add new base address
  2. Add new Endpoint with wsHttpBinding
  3. Give name to endpoints in case we may want to access separate Endpoint by providing Endpoint name the client

Add new base address as follows:

<add baseAddress="http://localhost:9001/MultipleBindingSelfHosted"/>

Add new Endpoint as follows. If you notice I have given name to the Endpoint as httpendpoint. You are free to give name of your choice.

<endpoint name="httpendpoint" address="http://localhost:9001/MultipleBindingSelfHosted" 
                  binding="wsHttpBinding" 
                  contract="MultipleBindingSelfHosted.IService1"/>


Also make sure that you have given a name to netTcpBinding Endpoint as well. Next let us go ahead and add metadata endpoint for http binding as well.

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

After configuring two Endpoints app.config of host application will look like as follows:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <system.serviceModel>

    <services>
      <service name="MultipleBindingSelfHosted.Service1" behaviorConfiguration="MultipleBindingSelfHostedBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:9002/MultipleBindingSelfHosted"/>
            <add baseAddress="http://localhost:9001/MultipleBindingSelfHosted"/>
          </baseAddresses>
        </host>
        <endpoint address="net.tcp://localhost:9002/MultipleBindingSelfHosted"
                  binding="netTcpBinding" 
                  contract="MultipleBindingSelfHosted.IService1"/>
        <endpoint address="mex"
                  binding="mexTcpBinding" 
                  contract="IMetadataExchange"/>
        <endpoint name="httpendpoint" address="http://localhost:9001/MultipleBindingSelfHosted" 
                  binding="wsHttpBinding" 
                  contract="MultipleBindingSelfHosted.IService1"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MultipleBindingSelfHostedBehavior">
          <serviceMetadata httpGetEnabled="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>
</configuration>


Once again go ahead and build and run the application. You should able to get host application running as follows:

image

We have successfully created a self-hosted service with multiple Endpoint. Now let us go ahead and create a client to consume the service. In console application, right click and add service reference. If client is in the same solution then use Discover option else copy paste base address from app.config file of the hosted application.

image

And then you can call the service for two Endpoints as follows

// calling service with TCP binding 
            Service1Client tcpproxy = new Service1Client("tcpendpoint");
            var result1 = tcpproxy.GetData(12);
            Console.WriteLine(result1);

            //calling service with HTTP binding 
            Service1Client httpproxy = new Service1Client("httpendpoint");
            var result2 = httpproxy.GetData(12);
            Console.WriteLine(result2);

            Console.ReadKey(true);


In this way you can create the self-hosted WCF service with multiple Endpoints. I hope this post is useful. Happy Coding!

Fault Contract’1 was unhandled by user code: Solved

For a training purpose I was trying a basic demo on fault contract in WCF and to be surprised I Got below error while throwing FaultException.

clip_image002

It’s not that 1st time I was working on Fault Contract but this error was irritating. After some investigation I found there was some issue in visual studio 2013 setting. So to solve this in Visual Studio go to Tools->Options.

In General tab from Debugging section uncheck following options,

  • Enable the exception assistant
  • Enable Just My Code
  • image

    Changes in Visual Studio setting should solve the problem. Keep in mind that above error can occur due to other reasons also. Visual setting debugging option may be one way to solve above said error. I hope you find it useful. Thanks for reading.