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.
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
hello.
send me a running sample to labreu at gmail.com and i'll try to take a look at it
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.
Hi, Can you upload your sample code here?
any chance of working source code. COuld you send it to me at sachabarber@hotmail.com
Pingback from Silverlight and JSON « Tales from a Trading Desk
Pingback from Ghillie Suits » Calling a WCF service from your Silverlight application - LA.NET [EN]
While you can easily use XML web services in your Silverlight applications, working with WCF is much
While you can easily use XML web services in your Silverlight applications, working with WCF is much
Hi,
I am trying to use a duplex service in Silverlight. Is that possible? If it is may I know how?
Pingback from MSDN Blog Postings » SoCal MSDN events for Web Developers - slide deck and links
Presentations given in Irvine and Riverside, CA - here's the deck and links for more information about
原文地址: http://msmvps.com/blogs/luisabreu/archive/2007/06/12/calling-a-wcf-service-from-your-silverlight-application.aspx