I wanted to share a couple of tips for calling web services from a Silverlight client.
If you are just beginning to useWeb Services from a Silverlight 2 Client, Tim Heuer has a good introductory post here.
Getting the Binding Url
A lot of the web service samples will show the binding created with a hardcoded Uri such as this:
WebServiceSoapClient webSvc = new WebServiceSoapClient(binding, new System.ServiceModel.EndpointAddress("http://localhost/MyWebService.asmx"));
The problem being of course that the EndpointAddress is hardcoded to localhost, and you may not know what server you will ultimately deploy to. You could add the Uri as a configuration setting, but there is a more flexible way.
Chances are, your web service is hosted on the same web server that your Silverlight application downloads from. So when you create your Web Service binding, you can determine the Url for you service to bind to based on the current browser Uri:
public static string GetUrlForResource(string resourcePage)
{
string webUrl = System.Windows.Browser.HtmlPage.Document.DocumentUri.ToString();
string containerPage = webUrl.Substring(webUrl.LastIndexOf("/") + 1);
webUrl = webUrl.Replace(containerPage, resourcePage);
return webUrl;
}
... So the method above, when passed a resource string such as "MyWebService.asmx" will return a full Url for a page that is in the same virtual directory as the silverlight app.
When binding, you can then use this utility method like so:
// get the full url of the Web Service
string webServiceUrl = GetUrlForResource("WebService.asmx");
System.ServiceModel.BasicHttpBinding binding = new System.ServiceModel.BasicHttpBinding();
WebServiceSoapClient webSvc = new WebServiceSoapClient(binding, new System.ServiceModel.EndpointAddress(webServiceUrl));
webSvc.HelloWorldCompleted += new EventHandler<HelloWorldCompletedEventArgs>(webSvc_HelloWorldCompleted);
webSvc.HelloWorldAsync();
Keep an Eye on MaxReceivedMessageSize
If your web service is returning a lot of data, you may blow out the default max message size for a return. If this happens you will get an exception like so:
An exception of type 'System.ServiceModel.CommunicationException' occurred in System.ServiceModel.dll but was not handled in user code
Additional information: [MaxReceivedMessageSizeExceeded]
To remedy this, you can up the MaxReceivedMessageSize attribute of the binding like so:
System.ServiceModel.BasicHttpBinding binding = new System.ServiceModel.BasicHttpBinding();
// if you are getting a LOT of data back, you will need to up Message Size
binding.MaxReceivedMessageSize = int.MaxValue;