Sunday, 1 July 2012

Cross Domain Calls to a Windows Communication Foundation (WCF) Services

Introduction

This blog focuses on calling a WCF service in a cross domain environment. To elaborate it, let us say the WCF service is hosted in a domain called http://wcf.com and the client application that requires to call the WCF service is hosted in a domain called http://client.com. Cross domain interaction between web resources has been a challenge as far as client scripting like Javascript, flush and others are concerned.

This blog provides a downloadable solution, links for further reading and a bit of explanation about some important web configuration sections and service properties.

JSON with Padding (JSONP)

JSONP is a complement to the JSON data format. The JSONP format enables a page to request data from a server in a different domain. See useful references.

The downloadable solution uses the JSONP format to make requests to the WCF service hosted in a different domain. The Jquery library supports the JSONP format requests in its $.ajax() and $.getJSON() methods. Later in this blog, there will be examples for both Jquery methods.

The WCF Service

The example WCF service is designed to return a list of customers when its GetCustomer method has been called. Key properties are highlighted.

.Net Framework 4 and Visual Studio 2010 are both required to compile the solution.


Service Designer (.svc)

<%@ServiceHost
    language="c#"
    Debug="true"
    Service="Microsoft.Samples.Jsonp.CustomerService"
    Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"
%>
 

Service Class (.cs)


using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Collections.Generic;
namespace Microsoft.Samples.Jsonp
{
    [DataContract]
    public class Customer
    {      
        [DataMember]
        public string FirstName;
       
        [DataMember]
        public string LastName;
    }


    [ServiceContract(Namespace="JsonpAjaxService")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class CustomerService
    {
        [WebGet( BodyStyle=WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
        public List<Customer> GetCustomer()
        {
            List<Customer> list = new List<Customer>();
            list.Add(new Customer() { FirstName="Nathan", LastName="Abebe"});
            list.Add(new Customer() { FirstName = "Dawit", LastName = "Yitagesu" });
            return list;
        }
    }
}
 

Web.Config

<system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="webHttpBindingWithJsonP"
                 crossDomainScriptAccessEnabled="true" />
      </webHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="webHttpBehavior">
          <webHttp helpEnabled="true"/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
        multipleSiteBindingsEnabled="true" />
    <services>
      <service name="Microsoft.Samples.Jsonp.CustomerService">
        <endpoint address="" behaviorConfiguration="webHttpBehavior"
            binding="webHttpBinding"
                  bindingConfiguration="webHttpBindingWithJsonP"
            contract="Microsoft.Samples.Jsonp.CustomerService" />
      </service>
    </services>    
  </system.serviceModel>

The Client (Javascript)

       var Type;
        var Url;
        var Data;
        var ContentType;
        var DataType;
        var ProcessData;
        var method;
       
        //Call service static class
        function CallService() {
            $.ajax({
                type: Type, //GET or POST or PUT or DELETE verb
                url: Url, // Absolute location of the service
                data: Data, //Data sent to server (Example {APIKey: 'your api key'})
                contentType: ContentType, // content type sent to server
                dataType: DataType, //Expected data format from server
                processdata: ProcessData, //True or False
                success: function (msg) {//On Successful response
                    ServiceSucceeded(msg);
                },
                error: ServiceFailed// On Unsuccessful response
            });
        }
        function ServiceFailed(xhr) {
            alert(xhr.responseText);
            if (xhr.responseText) {
                var err = xhr.responseText;
                if (err)
                    error(err);
                else
                    error({ Message: "Unknown server error." })
            }
            return;
        }
        function ServiceSucceeded(data) {                    
            if (DataType == "jsonp") {
                    $.each(data, function () {
                    var string = this.FirstName + " \n " + this.LastName;
                    alert(string);
                });
            }
        }
        //Url is consisted of {domain}/{service file}/{method name}
        //assuming the serivce file is found in the application root folder

        function getCustomerByJqueryAjax() {            
            Type = "GET";
            Url = "http://localhost:33695/service.svc/GetCustomer";
            DataType = "jsonp";
            ProcessData = false;
            method = "GetCustomer";
            CallService();
        }
        //Url is consited of {domain}/{service file}/{mothod name}{?callback=?}
        //assuming the serivce file is found in the application root folder
        function ajaxJsonPost() {

            $.getJSON("http://localhost:33695/service.svc/GetCustomer?callback=?",
                function (data) {
                    $.each(data, function (index, item) {
                        alert(item.FirstName + ' ' + item.LastName);                        
                    });
                });
            }            
        $(document).ready(function () {
            getCustomerByJqueryAjax();
            getCustomerByJqueryGetJson();
        });

Useful References

Windows Communication Foundation Sample Solution Downloads

JSONP for cross-site Callbacks

What is JSONP

1 comment: