WCF: Consume WCF REST service by HttpClient


In a recent case, one of my customers requested how to consume the WCF REST Service by taking the help of System.Net.Http.HttpClient modules (introduced in .NET 4.5). I hope the following details would help in depth.

 

Create a new WCF service application project named "RestService"

  • WCF REST service contract appears as the following.
		namespace RestService
		{
		    [ServiceContract]
		    public interface IService1
		    {
		
		        [OperationContract]
		        [WebInvoke(Method ="GET", ResponseFormat = WebMessageFormat.Json,
		            UriTemplate = "get/{value}")]
		        string GetData(string value);
		
		        [OperationContract]
		        [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json,
		            UriTemplate = "get/add")]
		        string AddData(int value);
		
		        [OperationContract]
		        [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json,
		            UriTemplate = "GetCustomer/{customerId}")]
		        Customer GetCustomer(string customerId);
		
		        [OperationContract]
		        [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json,
		            UriTemplate = "UpdateCustomer")]
		        List UpdateCustomer(Customer customer);
		    }
		
			[DataContract]
			public class Customer
			{
			        [DataMember]
			        public string Id { get; set; }
			        [DataMember]
			        public string FirstName { get; set; }
			        [DataMember]
			        public string LastName { get; set; }
			        [DataMember]
			        public string SSN { get; set; }
			}
                 }

 

  • The WCF REST service implementation appears as the following.
		namespace RestService
		{
		    public class Service1 : IService1
		    {
		        public static List customerList = null;
		
		        public Service1()
		        {
		            customerList = new List();
		
		            // Currently, it is statically loaded with dummy values.
		            // However, it can be extended to populate from a data source (e.g. SQL).
		            customerList.Add(new Customer
		            {
		                Id = "1111",
		                FirstName = "John",
		                LastName = "Doe",
		                SSN = "451234590"
		            });
		            customerList.Add(new Customer
		            {
		                Id = "1112",
		                FirstName = "Jason",
		                LastName = "Rudd",
		                SSN = "451234592"
		            });
		            customerList.Add(new Customer
		            {
		                Id = "1113",
		                FirstName = "Daniel",
		                LastName = "Cheng",
		                SSN = "451234596"
		            });
		        }
		        
		        public string GetData(string value)
		        {
		            return string.Format("You entered: {0}", value);
		        }
		
		        public string AddData(int value)
		        {
		            return string.Format("You entered: {0}", value);
		        }
		
		        public Customer GetCustomer(string customerId)
		        {
		            //TODO: query your repo and pull customer details
		            return customerList.Find(t => t.Id == customerId);
		        }
		        
		        public List UpdateCustomer(Customer customer)
		        {
		            //TODO: update customer information in your repo
		            var targetCustomer = customerList.Where(t => t.Id == customer.Id).FirstOrDefault();
		
		            if (targetCustomer != null)
		            {
		                // no need to update cutomerId
		                targetCustomer.FirstName = customer.FirstName;
		                targetCustomer.LastName = customer.LastName;
		                targetCustomer.SSN = customer.SSN;
		            }
		
		            return customerList;
		        }
		    }
                 }

 

  • Web.config should be updated like the following for WCF REST service hosting on IIS.
		<system.serviceModel>
		    <behaviors>
		      <serviceBehaviors>
		        <behavior>
		          <serviceMetadata httpGetEnabled="true"/>
		          <serviceDebug includeExceptionDetailInFaults="true"/>
		        </behavior>		      
            	    <endpointBehaviors>
		      <behavior name="ep">
		        <webHttp helpEnabled="true"/>
		      </behavior>
		    </endpointBehaviors>
		    </behaviors>
		    <services>
		      <service name="RestService.Service1">
		        <endpoint address=""
		                  binding="webHttpBinding" bindingConfiguration="webh" behaviorConfiguration="ep" contract="RestService.IService1"/>
		      </service>
		    </services>
		    <bindings>
			<!-- The following customBinding can be used if intention is to convert "webHttpBinding" to "customBinding" for some reason. -->
		      <customBinding>
		        <binding name="webHttpDeviceBinding">
		          <webMessageEncoding>
		            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
		              maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
		          </webMessageEncoding>
		          <httpTransport manualAddressing="true" maxBufferPoolSize="2147483647"
		            maxReceivedMessageSize="2147483647" authenticationScheme="None"
		            maxBufferSize="2147483647" maxPendingAccepts="15" transferMode="Buffered" />
		        </binding>
		      <webHttpBinding>
		        <binding name="webh">
		          <security mode="None" />
		        </binding>
		        <binding name="webHttpDeviceBinding" closeTimeout="00:10:00"
		          openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
		          maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
		          transferMode="Buffered">
		          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
		            maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
		          <security mode="None" />
		        </binding>
		      </webHttpBinding>
		    </bindings>
		    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
             </system.serviceModel>

 

Host the WCF REST service application on IIS

  • Create an application pool named "RestServicePool"
  • Right click on VS project "RestService" -> Go to "Web" section -> set server to "Local IIS"/ prepare your path and "Create Virtual Directory"
  • Application would be deployed on IIS
  • Select the application on IIS manager -> Go to "Advanced Settings" -> Set the application pool to your pool "RestServicePool"

 

Check if you are able to read "metadata" of the WCF REST service

Consume the REST service by HttpClient

  • Create a console application named "RestClient"
  • "Add Service Reference" to your service URL http://pupanda-win10.fareast.corp.microsoft.com/RestService/Service1.svc [reason to go for the plan of downloading proxy classes w.r.t. service classes, is to  ensure that custom classes can smoothly be "de-serialized" or "serialized"]
  • Go to your "Program.cs", update the definition with the following code snippet

 

        private static async Task PostResult()
		        {
		            HttpResponseMessage response = null;
		
		            using (var client = new HttpClient())
		            {
		                var uri = new Uri("http://pupanda-win10.fareast.corp.microsoft.com/RestService/Service1.svc/get/add");
		                var jsonRequest = JsonConvert.SerializeObject("123");
		                var stringContent = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
		                response = await client.PostAsync(uri, stringContent);
		            }
		
		            Console.WriteLine(await response.Content.ReadAsStringAsync());
		        }
		
		        private static async Task GetResult()
		        {
		            string response = null;
		
		            using (var client = new HttpClient())
		            {
		                var uri = new Uri("http://pupanda-win10.fareast.corp.microsoft.com/RestService/Service1.svc/get/123");
		                response = await client.GetStringAsync(uri);
		            }
		
		            Console.WriteLine(response);
		        }
		
		        private static async Task GetCustomerResult()
		        {
		            string response = null;
		
		            using (var client = new HttpClient())
		            {
		                var uri = new Uri("http://pupanda-win10.fareast.corp.microsoft.com/RestService/Service1.svc/GetCustomer/1113");
		                response = await client.GetStringAsync(uri);
		            }
		
		            Console.WriteLine(response);
		        }
		
		        private static async Task PostCustomerResult()
		        {
		            HttpResponseMessage response = null;
		
		            using (var client = new HttpClient())
		            {
		                var uri = new Uri("http://pupanda-win10.fareast.corp.microsoft.com/RestService/Service1.svc/UpdateCustomer");
		                Customer toUpdateCustomer = new Customer {
		                    Id = "1113",
		                    FirstName = "Daniel",
		                    LastName = "Gates",
		                    SSN = "4512xx596"
		                };
		                var jsonRequest = JsonConvert.SerializeObject(toUpdateCustomer);
		                var stringContent = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
		                response = await client.PostAsync(uri, stringContent);
		            }
		
		            Console.WriteLine(await response.Content.ReadAsStringAsync());
		        }
		
		        static void Main(string[] args)
		        {
		            Console.WriteLine("Press 1 for GET String/ Press 2 for POST String/ Press 3 for GET Customer/ Press 4 for POST Customer");
		            var input = Console.ReadLine();
		            switch (input)
		            {
		                case "1":
		                    Console.Write("Results from GET operation: ");
		                    Task.Run(() => GetResult());
		                    break;
		                case "2":
		                    Console.Write("Results from POST operation: ");
		                    Task.Run(() => PostResult());
		                    break;
		                case "3":
		                    Console.Write("Results from GET Customer operation: ");
		                    Task.Run(() => GetCustomerResult());
		                    break;
		                case "4":
		                    Console.Write("Results from POST Customer operation: ");
		                    Task.Run(() => PostCustomerResult());
		                    break;
		                default:
		                    Console.WriteLine("wrong option");
		                    break;
		            }
		
		            Console.ReadLine();
        }

 

Self-host the WCF REST Service

  • Create a console application named "RestServiceSelfHost"
  • Add reference to the "RestService" project
  • Update the "App.config" with following content
		      
		<system.serviceModel>    
		    <services>
		      <service name="RestService.Service1">
		        <host>
		          <baseAddresses>
		            <add baseAddress="http://localhost:8080/myrestservice"/>
		          </baseAddresses>
		        </host>
		        <endpoint address=""
		                  binding="webHttpBinding"
		                  behaviorConfiguration="epB"
		                  contract="RestService.IService1"/>
		      </service>
		    </services>
		    <behaviors>
		      <endpointBehaviors>
		        <behavior name="epB">
		          <webHttp helpEnabled="true"/>
		        </behavior>
		      </endpointBehaviors>
		    </behaviors>
		</system.serviceModel>            
  • Update the Program.cs with following content
		static void Main(string[] args)
		        {
		            using (ServiceHost host = new ServiceHost(typeof(Service1)))
		            {
		                host.Open();
		
		                Console.WriteLine("The service is ready at {0}", host.Description.Endpoints[0].Address);
		                Console.WriteLine("Press  to stop the service.");
		                Console.ReadLine();
		
		                // Close the ServiceHost.
		                //host.Close();
		            }
                       }

 

 

Consume the self-hosted WCF REST service by HttpClient

  • Create a console application named "RestServiceSelfHostClient"
  • Update your "Program.cs" with the following section of code
		 static void Main(string[] args)
		        {
		            Console.Write("Results from GET operation: ");
		            Task.Run(() => GetResult());
		
		            Console.ReadLine();
		        }
		
		        private static async Task GetResult()
		        {
		            string response = null;
		
		            using (var client = new HttpClient())
		            {
		                var uri = new Uri("http://localhost:8080/myrestservice/get/123");
		                response = await client.GetStringAsync(uri);
		            }
		
		            Console.WriteLine(response);
		        }

 

Note

I have uploaded the whole sample application for your reference in OneDrive. It is a one solution having all the above details.

Comments (0)

Skip to main content