Cross-Domain Policy Files for Flash and Silverlight with WCF
Introduction
In an earlier blog I described my motivation for upgrading an ASMX Web Service to WCF in a particular project.
In that project the client was a Flash client hosted in a web page. The upgrade was simple and, as long as I ran the client from within Flex Builder, it had no problem consuming the new self-hosted WCF service instead of the ASMX.
Allowing Cross-Domain Access
However, once I deployed the package outside the Flex Builder, all calls to the service failed. The reason was that the domain from which I had loaded the web page was not the same as the domain of the WCF service.
RIA applications like Flash and Silverlight regard such cross-domain accesses as potential security risks and block them - unless cross-domain policies on the server explicitly allow them. This requirement is relaxed in the development environment and enforced in a production environment, which explains why I had no problem during development.
So what if, like me, you would like certain services to serve clients even if they are loaded from other domains?
Well, the solution is to specify such permissions in a file called a Cross Domain Policy File and to make it accessible to clients at the domain URL. For instance, if your service resides at www.mycompany.com/Services/ProductsService.svc the file should be accessible as www.mycompany.com/crossdomain.xml.
Both Flash and Silverlight try to download such a file before accessing applications in the domain. By default they will look for a file called crossdomain.xml at the root of the domain. The Adobe cross-domain file specification can be found here. Tim Heuer shows how to create policy files for Silverlight here.
Problem: Exposing Cross-Domain Policy Files for a Self-Hosted WCF Service
When your service is being hosted by IIS it is easy to make the crossdomain.xml file accessible to clients, because it is straightforward to expose files using IIS. But, alas if you are using a self-hosted WCF service, it would seem that you are out of luck. Unless the WCF host delivers the crossdomain.xml file itself, it will not be accessible to remote clients.
Solution: Using WCF’s REST Support
Think about it, all we really need is to be able to respond to an HTTP Get request for the URL (such as www.mycompany.com/crossdomain.xml) by sending an HTTP response containing the contents of the cross-domain file.
WCF can easily support this with its support for RESTful services that I described in an earlier post.
Here are the configuration file and code snippets adapted where necessary for the task at hand.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="ProductsService"
behaviorConfiguration="ProductsServiceBehavior">
<endpoint address="ProductsService.svc"
binding="basicHttpBinding"
contract="IProductsService" />
<endpoint address=""
binding="webHttpBinding"
behaviorConfiguration="WebBehavior"
contract="IRestfulOperations" />
<host>
<baseAddresses>
<add baseAddress="http://www.mycompany.com/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="WebBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
and here is the code (adapted from an answer by Carlos Figueira here).
public partial class ProductsService : IProductsService, IPolicyRetriever
{
#region IPolicyRetriever Members
public Stream GetPolicy()
{
string result = @"<?xml version=""1.0""?>
<!DOCTYPE cross-domain-policy SYSTEM
""http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"">
<cross-domain-policy>
<allow-access-from domain=""*"" />
<allow-http-request-headers-from domain=""*"" headers=""SOAPAction""/>
</cross-domain-policy>";
WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
return new MemoryStream(Encoding.UTF8.GetBytes(result));
}
#endregion
}
Summary
In this post I described how you can use WCF’s REST support to have a self-hosted service expose the cross-domain policy file required by Silverlight and Flash when calling into Web services.
This is one more proof that WCF is extremely versatile interoperable and can be used in applications with a variety of requirements, including RIA in applications such as Flash and Silverlight.