我有一个自托管的WCF 4服务,通过basicHttpBinding为Silverlight 4客户端提供相同的合同,并为其他客户端提供wsHttpBinding。代码非常简短,在这里提供。
尝试从WCF访问服务方法时出现以下错误:
Message =尝试向URI发出请求时发生错误
http://localhost:8008/WCF4Silverlight.MyService/SL
。这可能是 由于尝试以跨域方式访问服务而没有 适当的跨域策略或不适合的策略 用于SOAP服务。您可能需要联系服务的所有者 发布跨域策略文件并确保它允许 要发送的与SOAP相关的HTTP标头。此错误也可能是由此引起的 使用Web服务代理中的内部类型而不使用 InternalsVisibleToAttribute属性。请查看内部异常 了解更多详情。
我确实有方法,GetClientAccessPolicy()使用WebGet属性提供跨域策略,我确信它有一个问题,它正确暴露。您对此问题的见解将受到高度赞赏。如果我在浏览器中键入http://localhost:8008/WCF4Silverlight.MyService/clientaccesspolicy.xml
,我会得到相同的xml,但Silverlight的调用总是因上述错误而失败。
以下是WCF服务的代码:
namespace WCF4Silverlight
{
[ServiceContract(SessionMode = SessionMode.NotAllowed)]
public interface IClientAccessPolicy
{
[OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]
Stream GetClientAccessPolicy();
}
}
namespace WCF4Silverlight
{
public class MyService: IMyService, IClientAccessPolicy
{
public Stream GetClientAccessPolicy()
{
const string result = @"<?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>";
if (WebOperationContext.Current != null)
WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml"; return new MemoryStream(Encoding.UTF8.GetBytes(result));
}
}
//Other service methods....
}
以下是发布服务的代码:
class Program
{
static void Main(string[] args)
{
ServiceHost myServiceHost = new ServiceHost(typeof(MyService));
myServiceHost.Open();
//Wait for client action.
myServiceHost.Close();
}
}
以下是WCF服务主机的app.config:
<service name="WCF4Silverlight.MyService" behaviorConfiguration="MyServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8008/MyService/"/>
</baseAddresses>
</host>
<endpoint address="general" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMyService" contract="WCF4Silverlight.IMyService"/>
<endpoint address="SL" binding="basicHttpBinding" bindingConfiguration="basicHttpBinding_IMyService" contract="WCF4Silverlight.IMyService"/>
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpBinding_IMyService" behaviorConfiguration="webHttpBehavior" contract="WCF4Silverlight.IClientAccessPolicy" />
</service>
以下是Silverlight客户端的ServiceReferences.ClientConfig:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
<customBinding>
<binding name="WSHttpBinding_IMyService">
<textMessageEncoding messageVersion="Default" writeEncoding="utf-8" />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://localhost:8008/MyService/SL"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyService"
contract="myWCFService.IMyService" name="BasicHttpBinding_IMyService" />
</client>
</system.serviceModel>
答案 0 :(得分:2)
这就是我为解决这个问题所做的工作:
1)使用Fiddler查看WCF调用的定向位置。 Fiddler告诉说这些调用未能成为HOST - http:/ localhost:8008和URL - /clientaccesspolicy.xml。
2)创建了一个实现IClientAccessPolicy的不同类ClientAccessPolicy(带有/clientaccesspolicy.xml的WebGet)。
3)在主机的app.config中添加了另一个部分,用于托管Clientaccesspolicy类的新服务。这个的基地址为http:/ localhost:8008 /
<service name="WCF4Silverlight.ClientAccessPolicy" behaviorConfiguration="ClientAccessPolicyBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8008/"/>
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpBinding_IMyService" behaviorConfiguration="webHttpBehavior" contract="WCF4Silverlight.IClientAccessPolicy" />
</service>
4)在托管代码中,创建了另一个ServiceHost实例并使用Clientaccesspolicy启动了新服务
ServiceHost clientAccessPolicyHost = new ServiceHost(typeof(ClientAccessPolicy)); clientAccessPolicyHost.Open();
5)在Silverlight客户端中,删除了对WCF的现有引用,并将其添加到新托管的服务中。
Silverlight的WCF调用正在进行中。
答案 1 :(得分:2)
在没有IIS的计算机上自托管服务,其中clientaccesspolicy 无法从root用户提供服务,而是可以使用此方法在端口80上动态提供策略:
答案 2 :(得分:1)
调试此类问题的最简单方法是使用Fiddler(www.fiddler2.com)拦截HTTP流量。您将立即查看是否请求了clientAccessPolicy.xml,它应该在何处,以及结果是什么。
如果你得到一个404(资源未找到),那么该文件不在预期位置(但你的webGet注释对我来说很好),否则问题就在xml本身内。
这是我通常用于开发/测试目的的非常许可的clientAccessPolicy.xml:
<?xml version="1.0" ?>
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>
答案 3 :(得分:0)
如果您使用的是自托管Web服务,则需要将ClientAccessPolicy.xml放入可在计算机端口80上访问的网站的根目录(例如http://localhost:80/ClientAccessPolicy.xml)。这是Silverlight 4中的新功能,不幸的是,我没有在MS文档中清楚地解释它。 (它已被提及,但它并不十分清楚。)