Create and consume WCF Restful Service using an HttpClient

Restful Services are getting more and more popular in our days and .NET developers prefer to build them through the Web API Framework, which let’s be honest it sounds right. You need to know though that WCF Framework also provides the support for building services that can be consumed over HTTP requests. This post will show you how easy is to create a WCF Restful service and consume it, either from a simple browser typing the right URL or from another application using an HttpClient.

Open Visual Studio and create a new WCF Service Application named WcfRestfulService. At this very moment, VS has created for you a WCF service using the default binding. You can test it by right clicking the Service1.svc file and view it on browser. We are going to change that service in order to be able to invoke it using HTTP requests. First right click Service1.svc and rename it to HttpService.svc. Also make sure you right click it again and view it’s Markup (View Markup option). Make the respective changes there too.

<%@ ServiceHost Language="C#" Debug="true" Service="WcfRestfulService.HttpService" CodeBehind="HttpService.svc.cs" %>

Delete the CompositeType from the HttpService.cs file changing it’s contents to the following.

using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfRestfulService
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
    // NOTE: In order to launch WCF Test Client for testing this service, please select Service1.svc or Service1.svc.cs at the Solution Explorer and start debugging.
    public class HttpService : IHttpService
    {
        public string GetData(string value)
        {
            return string.Format("You entered: {0}", value);
        }

    }
}

This HttpService class implements an IHttpService interface which has a simple OperationContract named GetData(int value). You guessed right, I have renamed IService1.cs file to IHttpService and made the following modifications.

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

namespace WcfRestfulService
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
    [ServiceContract]
    public interface IHttpService
    {

        [OperationContract]
        string GetData(string value);

    }
}

If you want to expose a WCF OperationContract over HTTP request, first thing you need to do is to annotate the OperationContract with a WebInvoke attribute. Also you need to provide it with “property-value” pairs in order to configure the exact way that this operation contract is going to be called. You can configure it for example to accept only POST Http requests or only GET. Parameters types need to be string and that’s why I changed value type from int to string. You can also configure the Response Format of the returned value but the most important is the UriTemplate attribute that defines the address where the OperationContract can be invoked. Modify the GetData operation contract inside the interface as follow:

[ServiceContract]
    public interface IHttpService
    {

        [OperationContract]
        [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Xml,
            BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "MyHttpGetData/{value}")]
        string GetData(string value);

    }

This OperationContract can be called with HTTP GET Requests such as

http://localhost:your_port/HttpService.svc/MyHttpGetData/random_number

Before consume that service we need to do one last thing. Change the default binding from basicHttpBinding to webHttpBinding in the Web.config file and make the respective changes to match our new Service names we renamed before. Your Web.config file should look like this:

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel >
    <services>
      <service
        name="WcfRestfulService.HttpService" behaviorConfiguration="ServiceBehaviour" >
        <endpoint address="" binding="webHttpBinding" behaviorConfiguration="web"
                  contract="WcfRestfulService.IHttpService">
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehaviour">
          <!-- 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>
      <endpointBehaviors>
        <behavior name="web">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
  </system.serviceModel >
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

</configuration>

Guess what. Your Http WCF service is ready. Build and run your solution. Try to invoke the OperationContarct GetData as follow:
wcfrestful_01
You will most likely want to invoke such an operation through another project, maybe an ASP.NET Web Application or just a simple console application. Let’s try to cover that too. Right click your solution and add a new ASP.NET Empty Web Application named WebClient. Add a new WebForm file named Default.aspx with a Code behind file. Change Default.aspx contents to the following:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebClient.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
        <br />
        <br />
        <asp:Label ID="Label1" runat="server"></asp:Label>
    
    </div>
    </form>
</body>
</html>

It’s a very simple aspx WebForm with a button to invoke our WCF Http Service and a label that will display the message returned from WCF Service. Time to bind our button’t Click event to a service call. Add to project a reference to System.Net.Http and then modify Default.aspx.cs contents as follow:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using System.Net.Http;

namespace WebClient
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            HttpClient client = new HttpClient();
            HttpResponseMessage wcfResponse = client.GetAsync("http://localhost:3729/HttpService.svc/MyHttpGetData/10").Result;
            HttpContent stream = wcfResponse.Content;
            var data = stream.ReadAsStringAsync();
            Label1.Text = data.Result;
        }
    }
}

When you want to make an HTTP call you use an HttpClient instance and it’s GetAsync method, passing the Restful Service’s URI. Build your solution, make sure both your projects are up and running (you may have to set them as StartUp projects) and click the button in the Default.aspx page. Click the following GIF image to watch it in action.
wcfrestful_02
There are so many and complicated operations that you can accomplish with WCF Restful Services and HttpClient applications you can’t even imagine.For example WCF Restful services can return appropriate HTTP Responses to client and clients can read from them specific property-value pairs and make respective actions. I hope we ‘ll have the chance to see them in action in later posts so stay in touch. Download the WcfRestfulServiceproject we have created from here. I hope you enjoyed the post.



Categories: ASP.NET, WCF

Tags: , ,

8 replies

  1. Nice article..

    But I have found another simple example to call a WCF RestFul Service using jQuery AJAX Call, please refer to link below:-
    http://www.etechpulse.com/2014/03/consume-restful-wcf-service-in-aspnet.html
    http://www.etechpulse.com/2014/03/how-to-consume-wcf-restful-service-in.html

    Thanks

  2. Very helpful post Chris!! I have been trying to save the xml output into the database. Can you point me on how I can achieve that?

    Thanks

  3. Do you mean to parse the XML output and save the inner value? You could write something like this to achieve it:

    HttpClient client = new HttpClient();
    HttpResponseMessage wcfResponse = client.GetAsync(“http://localhost:3729/HttpService.svc/MyHttpGetData/10”).Result;
    HttpContent stream = wcfResponse.Content;
    var data = stream.ReadAsStringAsync();
    Label1.Text = data.Result;

    // Parse XML value
    XmlDocument doc = new XmlDocument();
    doc.InnerXml = data.Result;
    XmlElement root = doc.DocumentElement;
    string ValueToDB = root.InnerText;

    Saving a value in db can be done through an INSERT SQL statement. Use an nvarchar type column to save the xml. You will find plenty of examples out on the internet and in this post on how to save data into a database using C#. You can use classes such as SqlConnection, SqlCommand or the Entity Framework.
    I hope i helped,

    Regards,

    C.S

  4. ok, thanks. That’s what I am trying to do. I am guessing am doing this in the client side which is the default.aspx page right? This is what I have…I am a little confused…all I need a Table in my DB right? Do I need to specify the connection string on the HttpService.svc as well? Do I need to create a store procedure? Thanks.

    protected void Button1_Click(object sender, EventArgs e)
    {
    //Fetching the value from the webservice
    HttpClient client = new HttpClient();
    HttpResponseMessage wcfResponse = client.GetAsync(“http://localhost:64046/HttpService.svc/MyHttpGetData/198”).Result;
    HttpContent stream = wcfResponse.Content;
    var data = stream.ReadAsStringAsync();
    Label1.Text = data.Result;

    //Parsing the XML Value

    XmlDocument doc = new XmlDocument();
    doc.InnerXml = data.Result;
    XmlElement root = doc.DocumentElement;
    string ValueToDB = root.InnerText;

    doc.Save(“test-doc.xml”);

    }
    private static void SaveToDb(string xml)
    {
    using (var conn = new SqlConnection())
    using (var command = new SqlCommand(“INSERT Result VALUES (@XML)”, conn))
    {
    command.Parameters.Add(“XML”, SqlDbType.Xml, xml.Length).Value = xml;
    conn.Open();
    var result = command.ExecuteNonQuery();
    }

    }

  5. Hi Chris, following up on my previous question, I tried to read/load xml and display that when I run service.svc in the browser. I have included the XML that I am loading, service and Iservice. The problem I am having is with the Iservice. Would you be able to look at my code? Thank you for your help.

    My XML

    1
    Chai
    1
    39
    Beverages

    Service.svc
    public string GetXMLData(string value)
    {
    XDocument doc = XDocument.Parse(Properties.Resources.Test);

    return Properties.Resources.Test;
    }

    IService
    [ServiceContract]
    public interface IService
    {
    [OperationContract]
    [WebInvoke(Method = “GET”, ResponseFormat = WebMessageFormat.Xml,
    BodyStyle = WebMessageBodyStyle.Wrapped,
    UriTemplate = “MyHttpGetData/{value}”)]
    string GetXMLData(string value);
    }

  6. Hi Chris, I was wondering how to save what have been displayed in the client side to the local drive? this line on Button1_Click? Thank you for your help.

    protected void Button1_Click(object sender, EventArgs e)
    {
    HttpClient client = new HttpClient();
    HttpResponseMessage wcfResponse = client.GetAsync(“http://localhost:3729/HttpService.svc/MyHttpGetData/10”).Result;
    HttpContent stream = wcfResponse.Content;
    var data = stream.ReadAsStringAsync();
    Label1.Text = data.Result;
    }

  7. After one year of fighting for the solution, today on 19th March 2015 I found this article and it saved me. I’m now able to talk between the WCF and ASP.NET using RESTFUL

Leave a comment