Debugging Services for Silverlight Applications

Microsoft Silverlight will reach end of support after October 2021. Learn more.

Silverlight version 4 enables accessing Web services that use Windows Communication Foundation (WCF) technology, ASP.NET Web Service technology, or practically any other SOAP, HTTP, or REST-based platform. When debugging a Silverlight application that accesses an external service, you can receive error messages that are difficult to interpret. This topic provides guidance to assist in debugging in the form of a checklist that itemizes some common possible problems. The each item in this checklist is elaborated on in a section that follows.

Debugging Checklist

  • Check Whether the Service Is Running

  • Check the Configuration

  • Check for Cross-Domain Issues

  • Check that Exceptions Have Been Enabled

  • Check What Is on the Wire

Check Whether the Service Is Running

Confirm that the service being accessed is working correctly before looking for problems on the Silverlight client side. One way to check on this is to type the service address into a Web browser. The service address required here is the value of the address attribute in the <endpoint> element of the ServiceReferences.ClientConfig file. Note that this is not the address that is typed into the Add Service Reference dialog. The service help page feature will often be available, and a page will be displayed after the address is entered that indicates whether the service is running correctly. If it is not, an error page indicates this and provides a message that can be used as a starting point for debugging.

A typically more reliable way to test whether the service is working is to use a test tool, such as the WCF Test Client, to try to talk to the service.

Another very reliable, but sometimes costly, way of finding out whether the problem is with the service code rather than with the Silverlight client code is to try using the service from a non-Silverlight client. Create, for example, a new console application type project, do an Add Service Reference to that project as in a Silverlight project, and add the service consumption code inside Main(), again, as you would with a Silverlight application. Use Console.WriteLine to show the results.

Check the Configuration

The first step is to check whether the Silverlight client is configured correctly. You should have a file called ServiceReferences.ClientConfig that is generated by the Add Service Reference tool. Examine the file for a Service1 client that is accessing a relevant service with an IService contract. The following code shows what the generated configuration file should look like.

<configuration>
    <system.serviceModel>
        <bindings>
            <customBinding>
                <binding name="CustomBinding_Service1">
                    <binaryMessageEncoding />
                    <httpTransport 
                            maxReceivedMessageSize="2147483647" 
                            maxBufferSize="2147483647" />
                </binding>
            </customBinding>
        </bindings>
        <client>
            <endpoint 
              address="https://localhost:59772/Service1.svc" 
              binding="customBinding"
              bindingConfiguration="CustomBinding_Service1"
              contract="ServiceReference1.Service1"
              name="CustomBinding_Service1" />
        </client>
    </system.serviceModel>
</configuration>

If you do not see an <endpoint> element for your service, your service probably was not actually configured correctly for access by a Silverlight 4 application. Silverlight 4 applications can talk only to simple SOAP services and cannot handle any advanced WS-* protocols like WS-Addressing or WS-Security. If you are using ASP.NET Web services, the client should just default to this simple configuration. For more information about the settings in the ServiceReferences.ClientConfig file, see Configuring Web Service Usage in Silverlight Clients.

If you are using WCF technology for the service, you should check the configuration on the service side, even if the client-side ServiceReferences.ClientConfig appears to be correct. Open the Web.config file from your service project and find the <system.serviceModel> element.

<system.serviceModel>
...

     <bindings>
         <customBinding>
             <binding name="SilverlightApplication1.Web.CustomerService.customBinding0">
                 <binaryMessageEncoding />
                 <httpTransport />
             </binding>
         </customBinding>
     </bindings>
     <serviceHostingEnvironment 
            aspNetCompatibilityEnabled="true"
            multipleSiteBindingsEnabled="true" />
     <services>
         <service name="SilverlightApplication1.Web.CustomerService">
             <endpoint address="" 
                       binding="customBinding" 
                       bindingConfiguration="SilverlightApplication1.Web.CustomerService.customBinding0"
                       contract="SilverlightApplication1.Web.CustomerService" />
             <endpoint address="mex" 
                       binding="mexHttpBinding" 
                       contract="IMetadataExchange" />
         </service>
     </services>
</system.serviceModel>

Find the <endpoint> element whose contract attribute refers to the service being accessed by the Silverlight 4 client. Make sure that the value of the binding attribute is set to “customBinding” and that the <customBinding> element specifies the <httpTransport> element. Additional <endpoint> elements are allowed for other contracts with other bindings. For example, the "mex" endpoint is used to provide metadata for the service in the preceding sample. For more information about configuring a service, see Configuring Services Using Configuration Files.

Check for Cross-Domain Issues

There are several URLs relevant to Silverlight applications and it is important to distinguish between them to frame the discussion of cross-domain issues that can arise. When you start your application, the URL that appears in the browser is referred to as the “application URL.” This URL will typically look something like https://localhost:1111/something/MyGraphicalApp.aspx Note that what really matters here is the URL of the XAP file, which might in this case look something like https://localhost:1111/somethingelse/MyGraphicalApp.xap, but in most of the simpler cases this URL will be in the same domain as the hosting Web page, so that this distinction can be disregarded. Next, look at the “service URL” in the ServiceReferences.ClientConfig file: some examples are https://localhost:5678/somepath/TestService.svc and local.live.com/SearchService/LocalSearch.asmx.

A common mistake that results in cross-domain issues is to run your Silverlight application from a file:// application URL. This problem can also be encountered when using the F5 functionality in Visual Studio 2010 to run your Silverlight application. To avoid this issue, right-click the .aspx page in your project instead and choose View in Browser.

To understand cross-domain issues, it is critical to know what part of a URL specifies the domain. The domain is basically everything between http:// and the first slash / that occurs next in the URL. This includes, for example, the port number (which is assumed to be 80 if it is not explicitly present). If the domain of the application URL is different from the domain of the service URL, you have a cross-domain situation. Even a difference in the port number or just one part of the domain name will result in such an issue. For example, if your application is at https://localhost:1111/something/MyGraphicalApp.aspx and it is trying to call into https://localhost:5678/somepath/TestService.svc, you have a cross-domain situation because localhost:1111 is a different domain than localhost:5678.

Access of a service across domains requires that the service have a cross-domain policy file. There are two kinds of cross-domain policy files: Clientaccesspolicy.xml and Crossdomain.xml. One of these must be present if you want services to work across domains. For more information, see Making a Service Available Across Domain Boundaries.

There is an easy way to check whether a service is set up correctly for cross-domain access. Open a browser and browse to http://service_domain/clientaccesspolicy.xml and then to http://service_domain/crossdomain.xml. If at least one of these is present, is valid, and is configured to allow cross-domain access, then the service will be accessible from domains other than the domain it is in.

A common mistake is to put the cross-domain policy file somewhere other than at the root of the domain: for example, putting a Clientaccesspolicy.xml file at https://localhost:5678/somepath/clientaccesspolicy.xml instead of at https://localhost:5678/clientaccesspolicy.xml. It is easy to run into this situation when working with older (say, .NET Framework 2.0, for example) projects.

Also, make sure to check the syntax of these files. An error in parsing one of the files is treated as if the file was not there. Note that the Clientaccesspolicy.xml and Crossdomain.xml files use different syntax. Make sure you use the appropriate content for the type of file that you choose to employ.

Check that Exceptions Have Been Enabled

For information on how to enable server exceptions so that they can be propagated to the client, see Creating and Handling Faults in Silverlight.

Check What Is on the Wire

The recommended way to debug Silverlight service consumption issues is by using an HTTP traffic-logging tool, such as Fiddler or Web Development Helper. These tools show you the actual HTTP traffic as it happens. Before using it, make sure to enable exceptions on the server as explained in the preceding section.

Start your Silverlight application and your tool side-by-side and have your application make a Web service call. Here are some common patterns you might see:

  • Nothing: Your HTTP spying tool might be configured incorrectly. Try running another, non-Silverlight application, like a regular Web browser, to make sure that the tool works correctly. Alternatively, your application might be broken. Put a breakpoint in where you invoke the service to make sure that the service is actually invoked. You might also have a configuration issue, in which case you should refer to the preceding configuration section. You might be trying to host your application from a file:// or https:// URL, or trying to call an https:// service.

  • Just a service request: If you see the actual request to the service on the wire, then you have avoided a cross-domain situation. Determine whether the address is what you expected it to be. Look at what is coming back on the wire. Is it timing out or are you getting a 404 error? Your service or even WCF itself might not be set up correctly. Are you getting a SOAP fault back? If so, read what is in the fault carefully, because it will usually have enough information to debug the issue. In general, look very carefully at both the request and the reply, including the body and HTTP headers. Did you remove anything to get the proxy to compile? The service might actually require some items that you removed. For example, it might require certain SOAP headers.

  • A request to Clientaccesspolicy.xml (and possibly to Crossdomain.xml afterwards), followed by a request to the service: You have a cross-domain situation, but you have successfully set up your cross-domain policy files. This is now essentially the same as the preceding bullet.

  • Only a request to Clientaccesspolicy.xml and nothing else: Most likely this is due to a malformed Clientaccesspolicy.xml, or one that contains a policy that forbids cross-domain access.

  • A request to Clientaccesspolicy.xml, then Crossdomain.xml, then nothing else: Basically, something probably went wrong with the cross-domain policy files. Are you getting 404 errors back? Check whether you are hosting the files correctly and in the correct locations. Are you getting the actual files back? Check to see whether they are malformed or forbid cross-domain access.