Междоменная ошибка Silverlight + WCF

Я прочитал большинство тем, охватывающих междоменную ошибку, и до сих пор не могу заставить ее работать. На сайте я загружаю модуль Silverlight, который связывается с веб-сервисом WCF. На локальном хосте работает нормально, ошибки не возникало.

У меня есть Webservice, размещенный на http://localhost:50283/, и в той же папке, к которой относится порт 50283. У меня есть файл clientaccesspolicy.xml, который выглядит следующим образом

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

Я поместил clientaccesspolicy.XML почти везде, включая \wwwroot, но это все равно не дало результата. Я могу получить доступ к clientaccesspolicy.xml как на локальном, так и на другом компьютере в той же сети ( http://computerIP:50283/clientaccesspolicy.xml отображает содержимое).
Я попытался перехватить ошибку, чтобы выяснить некоторые подробности о природе ошибки, но fiddler не фиксирует ошибки, только браузер. Буквально я все перепробовал и до сих пор без изменений. Кто-нибудь сталкивался с подобной проблемой и мог бы дать некоторые подсказки, где я должен искать решение?

Я столкнулся с аналогичной темой, но без решения, увы
Междоменная исключительная ситуация Silverlight-to-WCF, но файл clientaccesspolicy.xml успешно читается

2 ответа

Я помню, что сталкивался с этим много лет назад и решал его немного по-другому, а именно с помощью поведения. Учтите следующее:

using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.Xml;

internal class CrossDomainServiceBehavior : BehaviorExtensionElement, IEndpointBehavior
{
    private ServiceHost serviceHost;

    public override Type BehaviorType
    {
        get { return typeof(CrossDomainServiceBehavior); }
    }

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
        if (serviceHost == null)
        {
            serviceHost = new ServiceHost(typeof(CrossDomainPolicyService));

            string address = new Uri(endpoint.Address.Uri, "/").ToString();
            ServiceEndpoint crossDomainEndpoint = serviceHost.AddServiceEndpoint(typeof(ICrossDomainPolicyService), new WebHttpBinding(), address);
            crossDomainEndpoint.Behaviors.Add(new WebHttpBehavior());

            serviceHost.Open();
        }
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
    {
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
    {
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }

    protected override object CreateBehavior()
    {
        return new CrossDomainServiceBehavior();
    }
}

internal class CrossDomainPolicyService : ICrossDomainPolicyService
{
    public Message ProvideClientAccessPolicyFile()
    {
        XmlReader xmlReader = CreateClientAccessXml();
        return Message.CreateMessage(MessageVersion.None, string.Empty, xmlReader);
    }

    public Message ProvideCrossDomainPolicyFile()
    {
        XmlReader xmlReader = CreateCrossDomainXml();
        return Message.CreateMessage(MessageVersion.None, string.Empty, xmlReader);
    }

    private static XmlReader CreateClientAccessXml()
    {
        TextReader reader = new StringReader(@"<?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 XmlReader.Create(reader);
    }

    private static XmlReader CreateCrossDomainXml()
    {
        TextReader reader = new StringReader(@"<?xml version='1.0'?>
                                                  <cross-domain-policy>
                                                  <allow-http-request-headers-from domain='*' headers='*'/>
                                                  </cross-domain-policy>");
        return XmlReader.Create(reader);
    }
}

CrossDomainServiceBehavior должен быть добавлен к поведению в вашей службе WCF, и он использует CrossDomainPolicyService для динамического добавления междоменной политики. Это предотвращает необходимость добавления файла кросс-домена на сам сайт.

Добавление поведения из кода (например, с помощью собственных служб):

endPoint.Behaviors.Add(new CrossDomainServiceBehavior());

Или в случае определений WCF в config: для примера я буду предполагать, что CrossDomainServiceBehavior находится в пространстве имен Services.CrossDomainServiceBehavior, и сборка, в которой он находится, является версией 1.0.0.0 с нейтральной культурой. Также предполагается, что у вас есть привязка в объявлении сервиса, называемом webHttp.

Регистрация поведения:

<system.serviceModel>
  <extensions>
    <behaviorExtensions>
      <add name="CrossDomainServiceBehavior" type="Services.CrossDomainServiceBehavior, CrossDomainServiceBehavior.AssemblyName, Version=1.0.0.0, Culture=neutral" />
    </behaviorExtensions>
  </extensions>

Объявите поведение:

<behaviors>
  <endpointBehaviors>
    <behavior name="CrossDomainServiceBehavior">
      <webHttp/>
      <CrossDomainServiceBehavior/>
    </behavior>
  </endpointBehaviors>
<behaviors>

Добавьте поведение в привязку (здесь в качестве примера один называется webHttp):

<bindings>
    <webHttpBinding>
        <binding name="webHttp"
         maxReceivedMessageSize="20000000" >
            <security mode="None">
                <transport clientCredentialType = "None"/>
            </security>
        </binding>
        <CrossDomainServiceBehavior />
    </webHttpBinding>
</bindings>

Наконец, добавьте поведение к конечной точке службы, вот пример, который реализует ISomeService:

<endpoint address="" binding="webHttpBinding" contract="Services.ISomeService" bindingConfiguration="webHttp" behaviorConfiguration="CrossDomainServiceBehavior "/>

Не уверен, что это как-то связано с этим, но у меня похожая настройка, и мой clientaccesspolicy.xml выглядит немного иначе.

<?xml version="1.0" encoding="utf-8" ?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="SOAPAction">
        <domain uri="http://*"/>
        <domain uri="https://*" />
      </allow-from>
      <grant-to>
        <resource include-subpaths="true" path="/"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

Особенно разделение адресов http и https отличается. Помимо того, что вы пытаетесь сделать это с портом не по умолчанию, пробовали ли вы это на порте 80 по умолчанию? о, и в производственной среде эти * заменяются фактическим доменным именем.

Другие вопросы по тегам