views:

824

answers:

1

I have a Silverlight application on the client communicating with the server side through WCF. I keep getting a CommunicationException occasionally - and in particular when passing larger amounts of data to some parameters of the service. I have been told that if I want the Silverlight application to communicate with a server like this I need a clientaccesspolicy.xml file - to prevent cross site scripting.

So - I created the clientaccesspolicy.xml default like this:

<?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>

But now I don't know where to put it. And do I need to tell anyone where it is? And - might this be the solution to my problems?

+3  A: 

Yes, you need a clientaccesspolicy.xml when you want Silverlight to communicate with an outside source.

You did not specify whether the WCF service is hosted as a service, self-hosted, or hosted in IIS. If it is in IIS, then the file is placed in the root of the shared folder (website).

If the service is self-hosted, then you can read this article.

For a Windows Service, you can refer to the following article

But if you only get the error occasionally, then it probably is not your biggest issue. Looking at the fact that you say the errors occur when you try to send large parameters around, it means that you will have to look at the bindings of the WCF service, and the client. These limits are normally something like 16kb per call. This can be done on the service side, by creating a binding that will allow for large amounts of data to be passed.

<basicHttpBinding>
        <binding name="NewBinding0" maxBufferSize="104857600" maxReceivedMessageSize="104857600">
          <readerQuotas maxDepth="104857600" maxStringContentLength="104857600"
            maxArrayLength="104857600" maxBytesPerRead="104857600" maxNameTableCharCount="104857600" />
        </binding>
      </basicHttpBinding>

And then associate it to an endpoint.

If you look in your ServiceReferences.ClienConfig file on the client side, you should see a binding to a WCF service.

You can edit it to look something like:

<binding name="ProductConfig" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
                  <security mode="None" />
                </binding>

EDIT: Here is how to add the binding on the server side.

  • Right-click on web.config and say "edit WCF Configuration"
  • On the right, there is a tree element "Bindings"
  • Right-click on that and say "Add new binding"
  • Name the binding and set all the Max* elements to an arbitrarily large number.
  • Associate this binding to your endpoints, by expanding your services, and selecting the endpoint you are using. At the BindingConfiguration, select your new binding.

You can also manually add this to your web.config file, by finding the element

<system.serviceModel>

There should be a <bindings> child element somewhere in there. You can add the binding as shown above in there. And then scroll down to where your endpoints are shown and add a bindingConfiguration="NewBinding0" tag in the xml there.

EDIT Take 2:

Okay, sure, here is an example of what it looks like in one of my projects:

<system.serviceModel>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    <extensions>

    </extensions>
    <bindings>
      <basicHttpBinding>
        <binding name="NewBinding0" maxBufferSize="104857600" maxReceivedMessageSize="104857600">
          <readerQuotas maxDepth="104857600" maxStringContentLength="104857600"
            maxArrayLength="104857600" maxBytesPerRead="104857600" maxNameTableCharCount="104857600" />
        </binding>
      </basicHttpBinding>
      <mexHttpBinding>
        <binding name="NewBinding1" />
      </mexHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="policyBehavior">
          <webHttp />
        </behavior>
        <behavior name="NewBehavior" />
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="NewBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="NewBehavior" name="ALMWCFHost.ServiceModel">
        <clear />
        <endpoint address="GuildService" binding="basicHttpBinding" bindingConfiguration="NewBinding0"
          name="ProductConfig" contract="ALMWCFHost.IProductConfigModel"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://omrsrv004/" />
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>

IF you are having more issues with this, please provide details as to what IDE you are using, and how did you add your service endpoints originally.

Johannes
Thx for a good answer! You're probably right about my problem being a limit in parameter size. I'm new to these topics, so I wasn't aware about this. The settings on the client side are like you suggest already, but I'm not following on where to add the server side binding. The only place I see which sort of looks right is Web.config, but I don't really understand precisely what to do here..
stiank81
Thx again, but I'm sorry - I get no "edit WCF config" when right-clicking web.config. And doing it manually I find the <system.serviceModel>, but I don't find a <bindings> child. You wouldn't happen to have a sample <system.serviceModel> xml at hand so I can try creating what I need myself?..
stiank81
Adding NewBinding0 and setting this as bindingConfiguration for my service endpoint solved it. Thx a lot for your attention!
stiank81