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