Silverlight - WCF get clientaccesspolicy on localhost

2.7k views Asked by At

I have a Silverlight application which uses WCF for its communications with the server. Both Silverlight and WCF are running on the local machine (localhost). When the Silverlight makes a call to the service it fails with aa communication exception. I understand that this is because I don't have a clientaccesspolicy file, but since the WCF endpoint is running on http://localhost:port I defined an interface, IPolicyRetriver, and added an implementation to the service which is returning the clientaccesspolicy in a stream.

My question is, what do I have to configure so that it will run without a problem? I understand that I have to change or add something to my ServiceReference.ClientConfig file, but I don't understand what. I've included my ServiceReference.ClientConfig below. Please let me know what to change or add to it, and where in Silverlight to add this code. Please do not paste any links here to help me as I have opened every link I could during the last two days - but still don't understand.

<configuration>
<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IMapService" maxBufferSize="2147483647"
                maxReceivedMessageSize="2147483647">
                <security mode="None" />
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="../MapService.svc" binding="basicHttpBinding"
            bindingConfiguration="BasicHttpBinding_IMapService" contract="MapService.IMapService"
            name="BasicHttpBinding_IMapService" />
    </client>
</system.serviceModel>

HELP ME PLEASE!

2

There are 2 answers

2
DaveB On

You shouldn't need to change anything with your service configuration or code. Place the clientaccesspolicy.xml in the ROOT of the service website. If you are using Visual Studio, you may need to make a property change to get this to work. Silverlight will look for the existence of the file. I might help you to use a tool like Fiddler to see where Silverlight is looking for the file.

There is one link that I found very helpful but since you don't want any links, I won't provide it.

3
dlanod On

You haven't included the IPolicyRetriever implementation you mention, but here is a sample that you can use.

The interface specification:

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

    //[OperationContract, WebGet(UriTemplate = "/crossdomain.xml")]
    //Stream GetFlashPolicy();
}

The implementation of the interface:

    // IPolicyRetriever implementation
    private Stream StringToStream(string result)
    {
        WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
        return new MemoryStream(Encoding.UTF8.GetBytes(result));
    }

    public Stream GetSilverlightPolicy()
    {
        string result = @"<?xml version=""1.0"" encoding=""utf-8""?>
          <access-policy>
            <cross-domain-access>
              <policy>
                <allow-from http-request-headers=""*"">
                  <domain uri=""*""/>
                </allow-from>
                <grant-to>
                  <resource path=""/"" include-subpaths=""true""/>
                </grant-to>
              </policy>
            </cross-domain-access>
          </access-policy>";

        return StringToStream(result);
     }

Then you can include the following in your server's configuration XML file. This needs to be on the server side, not on the client side. I'm emphasising this because you included the client config above in your question.

<behaviors>
  <endpointBehaviors>
    <behavior name="WebHttpNewBehavior">
      <webHttp />
    </behavior>
  </endpointBehaviors>
  ...
</behaviors>
<services>
  <service behaviorConfiguration="NewBehavior">
    <endpoint behaviorConfiguration="WebHttpNewBehavior" binding="webHttpBinding"
                bindingConfiguration="" name="PolicyEndpoint" contract="WCFService.IPolicyRetriever" />
    ...
  </service>
</services>

Alternatively if you decide to create your host programmatically (this is how I do it, rather than use a ClientConfig file, so the above sample might not be 100% correct):

ServiceHost host = new ServiceHost(serviceType);
host.AddServiceEndpoint(typeof(IPolicyRetriever), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());

I know you asked not to provide links but I used http://blogs.msdn.com/b/asiatech/archive/2010/05/07/how-to-consume-a-self-hosted-wcf-service-in-a-cross-domain-environment-by-silverlight-client.aspx as a reference to refresh my memory, because I don't have access to my Silverlight/WCF project right at this minute.