Click here to Skip to main content
15,885,546 members
Articles / Web Development / HTML

Consume WCF Service with JSONP and SOAP endpoints

Rate me:
Please Sign up or sign in to vote.
4.86/5 (15 votes)
27 Jul 2012CPOL4 min read 87.5K   2.9K   44   20
Simple application that consumes a WCF Service with both jQuery/JSONP and XML/SOAP implementations.

Introduction  

A couple of months ago I started to play with some of the features of JSON objects when being consumed from a webservice. I decided to implement WCF to test the good integration with JSON data.

The outstanding article of Gary Stafford helped to configure my first JSON cross domain application consuming a REST/JSONP WCF service. That included the settings of a cross domain "JSONP endpoint" in the service.

The example covered part of the needs but it took me a week of research to configure the same WCF service for being consumed from a usual Service Reference SOAP proxy. At that stage, I required a second "endpoint" configuration. 

Background 

Remember first of all that JSONP or "JSON with padding" complements the JSON data format. It is used to request data from a server that is deployed in a different domain, something forbidden by many web browsers.  

WCF services are used in enterprise application development. Among many advantages, WCF can offer several endpoints on the same service (HTTP, TCP etc).  

By configuring a WCF service with JSONP and SOAP endpoints, you can make it accessible from different types of client. This is useful for the clients who can consume the WCF proxy and for the ones who run HTTP communication with JSONP data.  

The Representational State Transfer (REST) provides a direct response from the service in several plain formats. If the WCF service is using REST/JSONP, then it is not necessary for the client to consume the WCF service proxy.  

The REST/JSONP performance is relevant in Ajax applications that require JSON data to handle the front end presentation. Now it's possible to get that data with a simple HTTP communication.

The example

This example is basically a server application MyService that runs a WCF service with two different enpoints to be consumed by a web client application MyClient:

  • The SOAP endpoint is used from a client method loadDropDownSOAP() that populates an ASP dropdown list server control.   
  • The second REST/JSONP endpoint is also used by a JavaScript method loadDropDownJSONP() that attempts to populate another dropdown list. This time, the method only requires a HTTP call to get the data from the service.  

The client application look and feel is quite simple. Just press over "Load with JSONP call" and "Load with SOAP call" to launch both operations.  

Image 1

Using the code    

The zip folder contains both website applications implemented on Visual Studio 2010 (framework 4.0). MyService and MyClient are ready to be compiled and tested in local environment:   

  • MyClient. You can build and run the application. The client application will be executed on http://localhost:7726/
  • MyService. Also ready to be executed. The service will be running over http://localhost:6573/Service.svc

Below you can read further implementation details of the most relevant files.

MyService - Web.config     

Take a look at both endpoint and binding configuration. The SOAP request will have to handle with the address="soap" endpoint setting. 

Important to use binding="webHttpBinding" for the REST/JSONP endpoint and binding="basicHttpBinding" on the SOAP endpoint  

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

  <appSettings>
  </appSettings>
  <system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="false" />

    <services>
      <service behaviorConfiguration="WebServiceBehavior" name="MyService.Service">
        <endpoint address="" behaviorConfiguration="jsonBehavior" binding="webHttpBinding"
          bindingConfiguration="webHttpBindingWithJsonP" contract="MyService.IService" />
        <endpoint address="soap" binding="basicHttpBinding" contract="MyService.IService" />
      </service>
    </services>

    <behaviors>
      <endpointBehaviors>
        <behavior name="jsonBehavior">
          <webHttp helpEnabled="true"/>
        </behavior>
      </endpointBehaviors>

      <serviceBehaviors>
        <behavior name="WebServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <bindings>
      <webHttpBinding>
        <binding name="webHttpBindingWithJsonP"
                 crossDomainScriptAccessEnabled="true" />
      </webHttpBinding>
    </bindings>
  </system.serviceModel>

  <system.web>
    <compilation debug="false" targetFramework="4.0" />
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

MyService - Iservice.cs (Service Contract)

The format of the response is set in both operation contract. Either WebMessageFormat.Json or WebMessageFormat.Xml.

C#
[ServiceContract]
public interface IService
{
    [OperationContract]     
    [WebGet(BodyStyle = WebMessageBodyStyle.Bare,
    RequestFormat = WebMessageFormat.Json,
    ResponseFormat = WebMessageFormat.Json,
    UriTemplate = "/GetTourListJSONP/")]
    cTourList GetTourListJSONP();
             
    [OperationContract]       
    [WebGet(BodyStyle = WebMessageBodyStyle.Bare,
    RequestFormat = WebMessageFormat.Xml,
    ResponseFormat = WebMessageFormat.Xml,
    UriTemplate = "/GetTourListXML/")]
    cTourList GetTourListXML();
}

MyService - Service.scv.cs (implementation of IService interface)

Both service methods return a list of tours implemented in a class cTourList based in a collection of objects cTour.

C#
public class Service : IService
{
    public cTourList GetTourListJSONP()
    {
        return CreateTourList();
    }

    public cTourList GetTourListXML()
    {
        return CreateTourList();
    }
    
    private cTourList CreateTourList()
    {
        cTourList oTourList = new cTourList();
        oTourList.Add(new cTour() { ID = 1, description = "Barcelona" });
        oTourList.Add(new cTour() { ID = 2, description = "Paris" });
        oTourList.Add(new cTour() { ID = 3, description = "Rome" });
        oTourList.Add(new cTour() { ID = 4, description = "London" });
        oTourList.Add(new cTour() { ID = 5, description = "Moscow" });

        return oTourList;
    }
}

Once the service is running in Visual Studio, it's possible to test both endpoints with the WCF Test Client. Recommended to do so before using the final client application.

Image 2

MyClient - Web.config

SOAP calls from the client application will require Service Reference settings on the project. You can handle that opening Visual Studio 2010 -> Project -> Add Service Reference  

Image 3

After adding the Service Reference, make sure that the text "soap" is included in the "address" of the endpoint: address="http://localhost:6573/Service.svc/soap". Otherwise, the SOAP call won't be successful.

XML
<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="false" targetFramework="4.0" />
  </system.web>

  <system.webServer>
     <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>  
  
  <system.serviceModel>
    
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IService" closeTimeout="00:01:00"
          openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
          allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
          maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
          messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
          useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None"
              realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:6573/Service.svc/soap" binding="basicHttpBinding"
        bindingConfiguration="BasicHttpBinding_IService" contract="WCFReference.IService"
        name="BasicHttpBinding_IService" />
    </client>
    
  </system.serviceModel>
  
</configuration>

MyClient - Default.aspx.cs

The method loadDropDownSOAP() uses the endpoint SOAP that we commented above. The call returns an structure implemented in WCFReference.cTourList.

C#
public partial class _Default : System.Web.UI.Page
{
    protected void Button1_Click(object sender, EventArgs e)
    {
        // sets dropdown list empty
        DropDownListSOAP.Items.Clear();
        loadDropDownSOAP();
    }

    private void loadDropDownSOAP()
    {
        // XML-SOAP CALL TO WCF SERVICE
        WCFReference.ServiceClient oWebservice = new WCFReference.ServiceClient();
        WCFReference.cTourList oTourList = oWebservice.GetTourListXML();

        foreach (WCFReference.cTour oTour in oTourList)
        {
            DropDownListSOAP.Items.Add(new ListItem(oTour.description, Convert.ToString(oTour.ID)));
        }
    }
}

MyClient - Scripts/base.js 

This file contains the $.ajax call that will retrieve data from the WCF service in REST/JSONP mode using one specific endpoint configured on the WCF service. The var wcfServiceUrl contains the default HTTP address of the service.  

Note that the JavaScript method is populating the dropdown list using jQuery. The $.ajax call is returning a list of tours contained in the structure jsonpCallback: "tourList"

JavaScript
var wcfServiceUrl, populateDropdown;
 
// default URL WCF service
wcfServiceUrl = "http://localhost:6573/Service.svc/";


populateDropdown = function () {
    var ID, description;
    ID = this.ID;
    description = this.description;

    $("#selectJSON")
        .append($("<option></option>")
        .val(ID)
        .html(description));    
};

function loadDropDownJSONP(idDropdownJson, idDropdownSoap) {

    // sets both dropdown lists empty
    $("#" + idDropdownSoap + "").html("");
    $("#" + idDropdownJson + "").html("");

    // JSONP CALL TO WCF SERVICE
    $.ajax({
        cache: false,
        url: wcfServiceUrl + "GetTourListJSONP",
        data: "{}",
        type: "GET",
        jsonpCallback: "tourList",
        contentType: "application/javascript",
        dataType: "jsonp",
        error: function () {
            alert("list failed!");
        },
        success: function (list) {
            $.each(list, populateDropdown); // must call function as var
        }
   });
}

History 

  • 26/04/2012: First release of the article.  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Ireland Ireland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
arslan iub14-Oct-14 21:44
arslan iub14-Oct-14 21:44 
Questiona question about config application Pin
Member 1045809723-Jul-14 12:12
Member 1045809723-Jul-14 12:12 
AnswerRe: a question about config application Pin
Juan TF25-Jul-14 23:43
Juan TF25-Jul-14 23:43 
GeneralRe: a question about config application Pin
Member 1045809728-Jul-14 5:08
Member 1045809728-Jul-14 5:08 
GeneralRe: a question about config application - part of the solution Pin
Member 1045809731-Jul-14 9:31
Member 1045809731-Jul-14 9:31 
QuestionMy vote 5 Pin
Navin Pandit8-Apr-14 4:48
Navin Pandit8-Apr-14 4:48 
GeneralMy vote of 5 Pin
Amol_B10-Mar-14 21:29
professionalAmol_B10-Mar-14 21:29 
QuestionGreat article, enhancement suggestion Pin
Member 1000322021-Apr-13 14:16
Member 1000322021-Apr-13 14:16 
AnswerRe: Great article, enhancement suggestion Pin
Juan TF4-May-13 0:51
Juan TF4-May-13 0:51 
GeneralMy vote of 5 Pin
Peaceful Salman17-Apr-13 5:52
Peaceful Salman17-Apr-13 5:52 
QuestionVery well presented and concise. Exactly what I was looking for, one service 2 interfaces. Pin
Member 976801929-Jan-13 9:18
Member 976801929-Jan-13 9:18 
QuestionThank you Pin
Member 43673621-Dec-12 4:38
Member 43673621-Dec-12 4:38 
AnswerRe: Thank you Pin
Juan TF10-Dec-12 13:13
Juan TF10-Dec-12 13:13 
QuestionHow can we post Dictiontioary data (or key value pair) Pin
syed shabber raza rizvi18-Sep-12 2:48
syed shabber raza rizvi18-Sep-12 2:48 
AnswerRe: How can we post Dictiontioary data (or key value pair) Pin
Juan TF8-Nov-12 13:20
Juan TF8-Nov-12 13:20 
QuestionWhat about parameters? Pin
Vitor Canova15-Aug-12 6:24
Vitor Canova15-Aug-12 6:24 
AnswerRe: What about parameters? Pin
Juan TF15-Aug-12 13:56
Juan TF15-Aug-12 13:56 
BugAttachement is corrupted Pin
Sunasara Imdadhusen30-Jul-12 19:08
professionalSunasara Imdadhusen30-Jul-12 19:08 
GeneralRe: Attachement is corrupted Pin
Juan TF31-Jul-12 22:33
Juan TF31-Jul-12 22:33 
GeneralRe: Attachement is corrupted Pin
Sunasara Imdadhusen31-Jul-12 23:59
professionalSunasara Imdadhusen31-Jul-12 23:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.