views:

99

answers:

1

I am attempting to connect to an existing WCF service from silverlight (I have tried silverlight 4 and 3 so an answer for either would be great) that starts up via a windows service (though I am just running it from a command line project for the time being) rather than IIS and I am receiving the following error which looks as if it is clientaccesspolicy.xml related:

{System.ServiceModel.CommunicationException: An error occurred while trying to make a request to URI 'http://localhost:8082/SecurityService'. This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place, or a policy that is unsuitable for SOAP services. You may need to contact the owner of the service to publish a cross-domain policy file and to ensure it allows SOAP-related HTTP headers to be sent. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details. ---> System.Security.SecurityException ---> System.Security.SecurityException: Security error.
   at System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
   at System.Net.Browser.BrowserHttpWebRequest.<>c__DisplayClass5.<EndGetResponse>b__4(Object sendState)
   at System.Net.Browser.AsyncHelper.<>c__DisplayClass2.<BeginOnUI>b__0(Object sendState)
   --- End of inner exception stack trace ---
   at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
   at System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)
   --- End of inner exception stack trace ---
   at System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
   at System.ServiceModel.ClientBase`1.ChannelBase`1.EndInvoke(String methodName, Object[] args, IAsyncResult result)
   at SilverlightApplication1.ServiceReference1.SecurityServiceClient.SecurityServiceClientChannel.EndGetVersionInformation(IAsyncResult result)
   at SilverlightApplication1.ServiceReference1.SecurityServiceClient.SilverlightApplication1.ServiceReference1.SecurityService.EndGetVersionInformation(IAsyncResult result)
   at SilverlightApplication1.ServiceReference1.SecurityServiceClient.OnEndGetVersionInformation(IAsyncResult result)
   at System.ServiceModel.ClientBase`1.OnAsyncCallCompleted(IAsyncResult result)}

I have added another service within the services project so i can get the clientaccesspolicy.xml when querying the root of the service and can see in fiddler that this call is successful.

The services are configured as follows:

<behavior name="serviceMetadataBehavior">
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
      <serviceThrottling maxConcurrentCalls="30" />
      <serviceDebug includeExceptionDetailInFaults="true" />
</behavior>

...

<endpointBehaviors>
    <behavior name="serviceEndpointBehavior">
      <dataContractSerializer maxItemsInObjectGraph="2147483647" />
    </behavior>
    <behavior name="webEndpointBehavior">
      <webHttp/>
    </behavior>
  </endpointBehaviors>

...

  <service behaviorConfiguration="serviceMetadataBehavior" 
           name="PolicyService">
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8082" />
      </baseAddresses>
    </host>
    <endpoint binding="webHttpBinding" 
              name="PolicyEndpoint" 
              bindingName="" 
              contract="IPolicyService" 
              behaviorConfiguration="webEndpointBehavior" />
  </service>

...

<service behaviorConfiguration="serviceMetadataBehavior"  name="SecurityService">
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8082/SecurityService" />
        <add baseAddress="net.tcp://localhost:8083/SecurityService" />
      </baseAddresses>
    </host>
    <endpoint binding="basicHttpBinding" 
              bindingConfiguration="basicHttpBindingConfiguration" 
              name="SecurityServiceEndpoint" 
              bindingName="" 
              contract="ISecurityService" 
              behaviorConfiguration="serviceEndpointBehavior" />
  </service>

and the interfaces for these services are:

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

    [OperationContract, WebGet(UriTemplate = "/crossdomain.xml")]
    Stream GetCrossDomainAccessPolicy();
}
[Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WCF.ExceptionShielding("WebService")]
    [ServiceContract(Namespace = Namespaces.Services, Name = "SecurityService")]
    public interface ISecurityService
    {
        [OperationContract]
        [FaultContract(typeof(GeneralServiceFault))]
        Custom.VersionInformation GetVersionInformation(string userName);
    }

with the policy service returning the clientaccesspolicy.xml as a stream:

<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from>
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

if I need to give any more information please let me know. Any help much appreciated.

A: 

You should first investigate your issue further:

Use a tool like fiddler or Firebug to follow the client behavior and check if it is able to get the policy. Then check if it can get the good policy with the adequate syntax:

ClientAccessPolicy.xml and crossDomain.xml do not share the same syntax, then getting one with the other syntax would prevent your client from understanding it. You should therefore provide only one of the two.

Maupertuis
thanks for the response. I have checked with fiddler and I can see I am getting a 200 response when it queries for clientaccesspolicy.xml and that the response contains the the xml stated above. It doesn't look like it queries the crossdomain.xml, though I have included this and the content is different.
bobwah
Try to modify your allow-from element to allow SOAP-related HTTP headers. <allow-from http-request-headers="SOAPAction">
Maupertuis
looks like that got it working thnaks... might have another problem that the production environment uses net.tcp and is on a random 8000 port though :(
bobwah
If you use SL4, you are a lucky one then. Cross domain policy for sockets are considerably easier to deploy for SL4 than for SL3.
Maupertuis
can I connect to a net.tcp socket that is on an 8000 port without elevated level security though?
bobwah
Good point: The Silverlight runtime allows socket communication only from port 4502 to port 4532
Maupertuis
bah, you got my hopes up :( thought there might have been a way of doing it that i hadn't thought of. Thanks for the help though!
bobwah