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

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

У меня есть веб-сервис, размещенный на 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 отображает содержимое).
Я попытался перехватить ошибку, чтобы узнать более подробную информацию о ее природе, но скрипач не регистрирует никаких ошибок, это делает единственный браузер. Буквально все перепробовала и до сих пор без изменений. Кто-нибудь сталкивался с подобной проблемой и мог бы дать несколько советов, где мне искать решение?

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


person Maximus    schedule 02.03.2017    source источник
comment
Просто для устранения неполадок измените http-request-headers на http-request-headers="*", чтобы убедиться, что запросы могут идти, хотя разрешено, а затем работать в обратном направлении по мере добавления ограничений. Если со всеми разрешенными заголовками он по-прежнему не проходит, значит, проблема в другом. может быть установка брандмауэра?   -  person Nkosi    schedule 06.03.2017


Ответы (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 в конфигурации: для этого примера я предполагаю, что 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 "/>
person Huron    schedule 11.03.2017

Не уверен, что это связано с этим, но у меня аналогичная настройка, и мой 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? о, и в производственной среде эти * заменяются фактическим доменным именем.

person LeonG    schedule 10.03.2017