Calling a WCF service from your Silverlight application

Yesterday I talked about calling a traditional ASMX web service from your Silverlight app. Today, I'll be talking about WCF services. As I've said yesterday, in the current release, you only have tool support for getting a proxy to an ASMX web service (well, at least I've tried getting a web reference to a WCF service and it simply didn't work - maybe i'm doing something wrong). However, nothing prevents you from creating your own proxy to make the call to  a WCF service.

Since the alpha version only understands JSON when it calls ASMX services, I'm also assuming that is the only way you have to get info from a WCF service. That being the case, you must start by configuring your service to use JSON as its message enconding format.

After doing that, it's only a matter of  creating a new proxy class. Let me illustrate this with a quick example. Lets start by creating the dummy service:

[ServiceContract]
public interface ITest
{
    [OperationContract]
    S DoWork();
}

public class Test : ITest
{
    public S DoWork()
    {
        S a = new S();
        a.Address = "Funchal";
        a.Name = "Luis";
        return a;
    }
}

Don't forget to add the svc file :) (not shown here because there really isn't much to show, right). As you can see, this is really a stupid service which returns an object that only has two properties. Here's the S class (just for the sake of completeness):

[DataContract]
public class S
{
    [DataMember(Name="Name")]
    private string name = "Luis";
    [DataMember(Name="Address")]
    private string address= "Funchal";

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public string Address
    {
        get { return address; }
        set { address = value; }
    }
}

Now, the fun begins :) You must start by definig the S class in your silverlight project. You can do this in several ways:

  • you can add an existing cs file and then choose the link option (instead of clickin in the add button);
  • you might have built a dll with the previous type and then add it as reference to the service and silverlight projects;
  • there's always the old copy/paste approach :)

After doing that, you need to build a new type (the proxy) which you'll be using to communicate with the service. You must really build a new class because all the cool methods of the the SoapHttpClientProtocol class that you need to make the service calls are protected (the truth is that nothing prevents you from using the BrowserHttpWebRequest class and then using the JavaScriptSerializer to serialize/deserialize the values. If you find this funny, then by all means, go ahead and do it; i prefer to build the class in 30 seconds and then hit the coach to watch tv :))  . Here's a simple proxy that lets you invoke the DoWork method in a sync fashion:

public class MyProxy:SoapHttpClientProtocol
{
            public S DoWork()
            {
                object[] obj = this.Invoke("DoWork", new ServiceParameter[0], typeof(S));
                return (S)obj[0];
            }
}

Do notice the new ServiceParameter[0] value passed as the 2nd parameter of the Invoke method (needed because the method doesn't receive any parameters; if it expected parameters, you just need to pack them in an array and pass them to the Invoke method)...Getting the async methods is as easy as adding 2 methods which call the BeginInvoke/EndInvoke methods inherited from the base class. Using the proxy is really simple, as you  can see from the following code:

MyProxy proxy = new MyProxy();
proxy.Url = "url to the service";
S aux = proxy.DoWork();
Debug.WriteLine(aux.Name +"-"+ aux.Address);

And that's all for today.

Filed under: ,

Comments

# W James said:

Thanks for your work.  I've tried to duplicate a WCP service call at my end.  Unfortunately, I get an "Operation is not valid due to the current state of the object." error.  Forgive me for being a WCF newb.  I'm hoping that you can provide an answer to my dilema.  Here are some code snippets:

<Web.config>

<system.serviceModel>

<services>

<service name="TestService">

<endpoint contract="ITestService"

   binding="webHttpBinding" address=""

   behaviorConfiguration="jsonBehavior" bindingConfiguration="jsonBinding" />

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

</service>

</services>

<bindings>

<webHttpBinding>

<binding name="jsonBinding" messageEncoding="Json"/>

</webHttpBinding>

</bindings>

<behaviors>

<serviceBehaviors>

<behavior name="metadataSuport">

<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>

</behavior>

</serviceBehaviors>

<endpointBehaviors>

<behavior name="jsonBehavior">

<enableWebScript />

</behavior>

</endpointBehaviors>

</behaviors>

</system.serviceModel>

<TestService.svc>

<%@ ServiceHost Language="C#" Debug="true" Service="TestService" CodeBehind="~/App_Code/TestService.cs" %>

<app_code/ITestService.cs>

[ServiceContract]

public interface ITestService

{

   [OperationContract]

   string GetDataRows(string serviceName);

   [OperationContract]

   string HelloWorld();

}

<app_code/TestService.cs>

public class TestService : ITestService

{

   public string GetDataRows(string serviceName)

   {

       return "Dummy result";

   }

   public string HelloWorld()

   {

       return "Hi world!";

   }

}

<Default.xaml.cs>

   public class Proxy : SoapHttpClientProtocol

   {

       public Proxy(string url)

       {

           this.Url = url;

       }

       public string GetDataRows(string serviceName)

       {

           try

           {

               ServiceParameter[] parameters = new ServiceParameter[]

               {

                   new ServiceParameter("serviceName", serviceName)

               };

               object[] obj = this.Invoke("GetDataRows", parameters, typeof(string));

               return (string)obj[0];

           }

           catch (System.Exception error)

           {

               return error.Message;

           }

       }

       public string HelloWorld()

       {

           try

           {

               object[] obj = this.Invoke("HelloWorld", new ServiceParameter[0], typeof(string));

               return (string)obj[0];

           }

           catch (System.Exception error)

           {

               return error.Message;

           }

       }

   }

...

Proxy proxy = new Proxy("localhost/.../TestService.svc");

proxy.HelloWorld();

I'm sorry about posting all this code to your forum.  I'm stumped and didn't know where else to turn.  It's probably not the best way to introduce myself.

I've followed your code examples as closely as possible.  I've tried the proxy url without the ".svc" extension as well and come up with the same issue.

Any help you can lend is greatly appreciated.

W James

Thursday, July 05, 2007 8:53 AM
# luisabreu said:

hello.

send me a running sample to labreu at gmail.com and i'll try to take a look at it

Thursday, July 05, 2007 3:16 PM
# Swati said:

Thanks for this useful information:

Actually i am trying to call a WCF Service from a SilverLight application. Silverlight provides add webreference but i cann't get the object of reference and hence can not call the WCF service..

Would you please highlight more upon your writeup.

Monday, July 23, 2007 8:08 AM
# Walter said:

Hi, Can you upload your sample code here?

Friday, July 27, 2007 2:59 AM
# sacha barber said:

any chance of working source code. COuld you send it to me at sachabarber@hotmail.com

Thursday, October 18, 2007 2:33 AM
# Silverlight and JSON « Tales from a Trading Desk said:

Pingback from  Silverlight and JSON &laquo; Tales from a Trading Desk

Friday, October 26, 2007 3:02 PM
# Ghillie Suits » Calling a WCF service from your Silverlight application - LA.NET [EN] said:

Pingback from  Ghillie Suits &raquo; Calling a WCF service from your Silverlight application - LA.NET [EN]

Tuesday, October 30, 2007 1:46 PM
# Zhiming Xue's WebLog said:

While you can easily use XML web services in your Silverlight applications, working with WCF is much

Wednesday, October 31, 2007 9:08 AM
# Noticias externas said:

While you can easily use XML web services in your Silverlight applications, working with WCF is much

Wednesday, October 31, 2007 9:50 AM
# Reece Sim said:

Hi,

I am trying to use a duplex service in Silverlight. Is that possible? If it is may I know how?

Thursday, November 22, 2007 7:55 PM
# MSDN Blog Postings » SoCal MSDN events for Web Developers - slide deck and links said:

Pingback from  MSDN Blog Postings  &raquo; SoCal MSDN events for Web Developers - slide deck and links

Monday, December 03, 2007 6:33 PM
# Contagious Curiosity said:

Presentations given in Irvine and Riverside, CA - here's the deck and links for more information about

Wednesday, December 05, 2007 10:11 AM

Leave a Comment

(required) 
(required) 
(optional)
(required)