Self-Hosted WCF Service for Silverlight

Visual Studio 2010 includes the ability to build new projects based on project templates published to the Visual Studio Gallery. I published a template that includes the necessary configuration and classes to quickly build a self-hosted WCF service library for Silverlight clients. The template can be found in the “WCF” and “Silverlight” categories of the Visual Studio Gallery.

clientaccesspolicy.xml

The primary difference in my project template and the standard WCF service library template is the service contract and implementation method to serve the “clientaccesspolicy.xml” file required for cross-domain service calls from Silverlight clients. This file is automatically downloaded by the Silverlight runtime when the application attempts to access a network resource. If you were to host your service in IIS you would simply place the policy file on the root of the web server. However, since there is no web server when you self-host your services, this template uses the System.ServiceModel.Web.WebGetAttribute class to specify a web method to handle the request for the policy file.

    [ServiceContract]
    public interface IClientAccessPolicy
    {
        [OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]
        Stream GetPolicy();
    }

 

The GetPolicy() method will return a stream containing the contents of the policy file. The specific policy you wish to enforce should be specified as part of the string built and returned in this method.

        System.IO.Stream IClientAccessPolicy.GetPolicy()
        {
            // TODO: Modify the string below to set the desired cross-domain policy
            string result = @"<?xml version=""1.0"" encoding=""utf-8""?>
<access-policy>
    <cross-domain-access>
        <policy>
            <allow-from http-request-headers=""*"">
                <domain uri=""http://*""/>
            </allow-from>
            <grant-to>
                <resource path=""/"" include-subpaths=""true""/>
            </grant-to>
        </policy>
    </cross-domain-access>
</access-policy>";

            WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
            return new MemoryStream(Encoding.UTF8.GetBytes(result));
        }

 

App.config

The default App.config file included with the template has been modified from the original service library config file in a few important ways. It includes an endpoint configured for the binary encoding released with Silverlight 3. This is implemented as a custom binding. Also, there is an endpoint for the service contract which defines the GetPolicy() method to serve the policy file. It is configured to use the WebHttpBinding class and has an endpoint behavior configured with the <webHttp> element to enable the WCF web programming model. Finally, the base address for the service has been modified so that it now only specifies a server (localhost) and port number (8732) to use as a base address. The default service template adds a path to the base address URL beginning with “Design_Time_Addresses”. The base address must specify the root of the server since that is where the Silverlight runtime will look for the clientaccesspolicy.xml file.

    <bindings>
      <customBinding>
        <binding name="binaryHttpBinding">
          <binaryMessageEncoding />
          <httpTransport />
        </binding>
      </customBinding>
    </bindings>

    <services>
      <service name="SLServiceLibrary.Service1" behaviorConfiguration="SLServiceLibrary.ServiceBehavior">
        <endpoint address="Service1"
                  binding="customBinding"
                  contract="SLServiceLibrary.IService1"
                  bindingConfiguration="binaryHttpBinding" />
        <endpoint address=""
                  binding="webHttpBinding"
                  contract="SLServiceLibrary.IClientAccessPolicy"
                  behaviorConfiguration="webHttpEnablingBehavior" />
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8732/" />
          </baseAddresses>
        </host>
      </service>
    </services>

 

Console Host

The template includes a second project called “ConsoleHost” which is simply a console application configured to host the service. The App.config file for the host project is identical to the one in the service library project with the exception of it using a different port number in the base address (8733). In a production environment it would almost certainly be preferable to host the WCF service in a Windows Service. However, a console application is much more convenient when debugging in Visual Studio.

The console host application should be configured as the default start-up project when debugging in Visual Studio. When the project is run you should be able to type the following address in a browser and receive the contents of the clientaccesspolicy.xml “file”:

http://localhost:8733/clientaccesspolicy.xml

You will then be ready to add a Silverlight application to the solution and create a service reference from it to your new self-hosted service and use it as you would any other service for Silverlight clients.

Enjoy.

13 Comments

Patrick SchallerNovember 29th, 1999 at 7:00 pm

Am I misunderstanding or can I use this for my Data Access to a locally deployed SQL DB for an OOB Silverlight 4 application? Is that not a possible usage scenario?

Thanks for the effort regardless.

wytekNovember 19th, 2010 at 1:06 pm

I have installed your projec ttemplate but it does not show up in VS 2010.

Any idea why not?

carstenDecember 3rd, 2010 at 11:15 am

It took me a while to find that project template, too. In the “Add new project”-window do NOT select WCF or Silverlight – it is located unter Vicual C# and is named ‘Self-Hosted WCF Service for Silverlight’ as expected.

Brice WilsonJanuary 7th, 2011 at 11:26 am

Patrick – I have never run a Silverlight application out-of-browser, but the following MSDN article says that Silverlight 4 applications which run out-of-browser can be configured for elevated trust allowing it to access network resources without the need for a policy file. Running your app that way would eliminate the need for my project template since it’s main purpose is to serve the policy file. See the “Trusted Applications and Elevated Trust” section of the article at http://msdn.microsoft.com/en-us/library/cc645032(v=vs.95).aspx.

sergeJanuary 31st, 2011 at 6:12 pm

Based on you domain uri setting, the HTTP-hosted SL client should be able to access an HTTPS endpoint. When I try to do that, I get the crossdomain access exception. I can access my secure endpoint from a WCF client, so, this tells me that the SSL is configured correctly. Also, I can access the non-secure endpoint from my SL client, which means that the clientaccesspolicy.xml is generated correctly, and when I set a breakpoint in GetPolicy(), the code does break.
I was wondering if you ever tried to access an HTTPS endpoint from your SL client, and did it work?

Thank you!

Brice WilsonJanuary 31st, 2011 at 8:02 pm

Serge – I suspect you need to modify the policy file served from GetPolicy() to allow HTTPS requests. The article below describes what is allowed or denied when using wildcard characters in your policy file. About halfway through the article there are matrices describing what is allowed if your Silverlight client is hosted via HTTP or HTTPS when trying to access a service which is hosted via HTTP or HTTPS. It lists every combination. Take a look at that and see if the combination you are using is actully allowed.

http://msdn.microsoft.com/en-us/library/cc645032(v=vs.95).aspx

sergeFebruary 1st, 2011 at 9:19 am

Yes, I used exactly the matrices in the article you mentioned to make sure my clientaccesspolicy.xml file has the proper domain URI. The second matrix has for the HTTP-hosted SL client and HTTPS Service, the as “Allowed”.

Thanks again!

sergeFebruary 1st, 2011 at 10:33 am

Brice – one more question: do you know if there is a tool, or some technique that would allow a developer to troubleshoot this issue?

Thanks!

Brice WilsonFebruary 1st, 2011 at 4:44 pm

Serge – I have used Fiddler to diagnose several weird problems with Silverlight services. It will log all of the HTTP traffic from your client machine and show you lots of detail about the requests including the HTTP response code. I would also make sure you can simply view your clientaccesspolicy.xml file in a browser. Once your service is running you should be able to browse to the address of the policy file and see it displayed in your browser. Make sure you use HTTPS to access it if that is how your Silverlight application will access it.

Here is a link to Fiddler:

http://www.fiddler2.com/fiddler2/

sergeFebruary 2nd, 2011 at 4:00 pm

Brice – thanks to your suggestion to try to view the policy file from a browser, made me realize that I wasn’t placing the file in the correct root. I also had to set the “include-subpaths” attribute to “true”, – I couldn’t find the meaning of this attribute in the specification for the clientaccesspolicy but without setting it to “true” the call fails. Also, I had to set WebHttpSecurityMode to “Transport” on WebHttpBinding. This allowed my SL client to call WCF service over HTTPS.
There are still an issue that I am seeing: when the call is made now, a login dialog pops up asking for credentials. I explicitly set credentials on the channel factory of my main service (in your sample that would be Service1) but, it seems that the first call to the IClientAccessPolicy.GetPolicy() that the runtime makes requires credentials to be set. I tried to create the IClientAccessPolicy proxy myself, set the credentials on the proxy explicitly and call GetPolicy() but that didn’t help. I expected that, if I set the credentials on my Service1 proxy, the calls will be made without any login prompts. Maybe there are some additional attributes within the policy file that need to be set for it to work the way I expect, I will need to go through the spec some more.
I was wondering whether you have seen this issue and know where to look, that would have saved me time :-)

Thanks again!

Brice WilsonFebruary 2nd, 2011 at 8:02 pm

Serge – I don’t think I’ve ever been faced with implementing an architecture like the one you described. I’m afraid the best I can do is direct you to MSDN and Google. Good luck!

Brice

AliJune 23rd, 2011 at 1:50 am

Actually I am Brand New to Siverlight So I have no idea about anything. Can You Please Give me a little help on How to Host WCF Data Service using ur tempelate

or what modifciation I must do In my Current Project That Works fine If Hoster on IIS but I do not know how to self host services in it.

Another thing. When I tried to Add WCF DAta Service in ur Project. I was unable to find WCF DAta Service STrange But True

Brice WilsonJune 23rd, 2011 at 4:25 pm

Ali – I only have limited experience with WCF Data Services, but I think it is expected that they will be hosted in IIS. Therefore, to access it with Silverlight, I would think you would only need to make a clientaccesspolicy.xml file available on the server. I don’t know that my self-hosting project template is really what you’re looking for if you need the functionality of WCF Data Services (OData).

Leave a comment

Your comment