Silerlight调用WCF、Web Service、Wcf Ria Service跨域的问题

来源:互联网 发布:剑三大师脸型数据 编辑:程序博客网 时间:2024/05/22 07:47


Silerlight调用WCF、Web Service、Wcf Ria Service跨域的问题 

转自:http://www.cnblogs.com/Joetao/articles/2213800.html 

            我们往往需要调用已建好的WCF,Web Service,Wcf Ria Service,这些调用的程序项目往往是另开一个的一个解决方案,这往往导致调用服务者和发布服务者不是同一个服务器上,即使在同一服务器上,因程序的端口好不同,而会产生跨域的问题。

(一)原因分析:

Silverlight 在默认情况下只允许源站点通信。例如,在 http://contoso.com/mycontrol.aspx 上承载的 Silverlight 控件默认只能访问同一域中的服务(例如 http://contoso.com/service.svc),而不能访问位于 http://fabrikam.com/service.svc 的服务。这可以避免在 http://contoso.com 域上承载的恶意 Silverlight 控件对 http://fabrikam.com 域上承载的服务调用未授权操作。

(二)跨域粉墨登场

就是因为这些原因,而跨域能解解决不同站点调用非本地站点服务,所以跨域就水到渠成的登场了

(三)如何跨域

只需要在你的*.Web服务端的根目录下放上两个文件clientaccesspolicy.xml 和crossdomain.xml

(1)clientaccesspolicy.xml 以配置服务允许跨域访问

复制代码
<?xml version="1.0" encoding="utf-8"?><access-policy>  <cross-domain-access>    <policy>      <allow-from http-request-headers="*">        <domain uri="*"/>      </allow-from>      <!--只允许从其他域中的一个访问,如http://contoso.com             <allow-from http-request-headers="*">        <domain uri="http://contoso.com"/>      </allow-from>            -->      <!--允许访问 HTTPS 服务             <allow-from http-request-headers="*">        <domain  uri=”http://*”/>      </allow-from>            -->          <grant-to>        <resource path="/" include-subpaths="true"/>      </grant-to>    </policy>  </cross-domain-access></access-policy>
复制代码

(2) crossdomain.xml 该文件必须将整个域标记为 public

<?xml version="1.0" ?><cross-domain-policy>  <allow-access-from domain="*" /></cross-domain-policy>

(四)实战训练

(1)新建项目SilverlightWCF,并在*.Web端添加一个WCF服务,记得一定是选择“启动了Silverlight的WCF服务”,如下图

代码如下

CustomerService.svc
复制代码
using System;using System.Linq;using System.Runtime.Serialization;using System.ServiceModel;using System.ServiceModel.Activation;namespace SilverlightWCF.Web{    [ServiceContract(Namespace = "")]    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]    public class CustomerService    {        [OperationContract]        public int CountUsers()        {            return 2;        }        [OperationContract]        public User GetUser(int id)        {            if (id == 1)            {                return new User() { IsMember = true, Name = "Paul", Age = 24 };            }            else            {                return new User() { IsMember = false, Name = "John", Age = 64 };            }        }        // 在此处添加更多操作并使用 [OperationContract] 标记它们    }    //需要注意点    //(1)默认情况下,DataContractSerializer 序列化所有公开可见的类型,包括这些类型的所有公共的读/写属性和字段    //   不需要应用 DataContractAttribute 和 DataMemberAttribute 以选择使用序列化过程    //(2)如果不使用“启用 Silverlight 的 WCF 服务”模板创建 WCF 服务,则必须确保使用 BasicHttpBinding 配置 WCF 服务,以便支持该服务。    //(3)使用“启用 Silverlight 的 WCF 服务”模板时,Web.config 文件会自动改为启用 ASP.NET 兼容模式,以便于将您的支持服务的 Silverlight 应用程序与 ASP.NET 安全模型相集成    //   这样您就可以完成很多工作,例如,可以限制仅通过身份验证的用户拥有对特定服务的访问权限,或者限制拥有特定角色的用户拥有访问权限    //   启动ASP.NET兼容模式:在web.config文件中产生AspNetCompatibilityRequirements 特性配置为允许 ASP.NET 兼容模式。    public class User    {        public bool IsMember { get; set; }        public string Name { get; set; }        public int Age { get; set; }    }}
复制代码

(2)新建一个项目,叫InvokeSilverlightWCF,添加服务引用。如果没有在项目SilverlightWCF.Web下添加两个跨域文件clientaccesspolicy.xml 和crossdomain.xml 就会报错,报错如下:

尝试向 URI“http://localhost:6053/CustomerService.svc”发出请求时出错。这可能是由于试图以跨域方式访问服务而又没有正确的跨域策略,或策略不适用于 SOAP 服务。您可能需要与该服务的所有者联系,以发布跨域策略文件并确保该文件允许发送 SOAP 相关的 HTTP 标头。出现此错误也可能是由于使用的是 Web 服务代理中的内部类型而没有使用 InternalsVisibleToAttribute 属性。有关详细信息,请参阅内部异常。

解决这个问题,如前面所述方法就可以解决了

(五)后续的话题

      上面所说的是调用自己建的服务,如果存在跨域问题,自己想添加两个跨域文件clientaccesspolicy.xml 和crossdomain.xml 是非常容易的,就可以解决问题。但是像调用

中国气象局的天气预报服务http://www.webxml.com.cn/WebServices/WeatherWebService.asmx,你不可能叫别人为你一个人添加clientaccesspolicy.xml 和crossdomain.xml 跨域问题吧,因为WebService在其他客户的时不会存在这样的问题。

      既然上面的路行不通,我的做法就是在Silverlight应用程序的服务端新建一个WCF,而这个WCF中的方法调用http://www.webxml.com.cn/WebServices/WeatherWebService.asmx的服务方法,然后Silverlight应用程序的Web端就具有这些服务方法了,在同Silverlight的Client端添加Silverlight的WCF服务,这个过程就不会发生跨域的问题了,因为他们在同一个解决方案域中。这种办法相当于把不能被Siilverlight调用服务,经过Silvelight服务端包裹后,就供Silverlight的Client调用。

      关于Silvelight的跨域问题就写到这里了,凌晨1:37该睡觉了!

源代码下载

分类: Silverlight, WCF
0 0
原创粉丝点击