您的位置:首页 > 其它

Silverlight 调用自托管的wcf 报跨域异常的处理

2016-01-24 15:27 302 查看
Sileverlight很多时候需要通过wcf和后台,程序进行交互。如果 iis was托管还好,极端的遇到自托管的程序,console,windowsservice,winform,wpf等,就会出现跨域问题。网上很多解决方式。俺在以下博文基础上又总结了点。
  以下博文可以先学习下:

    /article/11687540.html

    http://blog.sina.com.cn/s/blog_74066ace0100vhs5.html

    /article/5139625.html

以下是个人总结

1.此解决方案与Silverlight版本无关。

2.可以跨进程托管Domain

3.可以不写配置文件托管Domain和Service

4.可以用 Stream和Message当Domain返回值

5.不通过配置实现的自托管代码如下:

跨域解决方案

方案1:

  1.在项目中加入clientaccesspolicy.xml,编译生成内容,复制=true

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


   2. 加入域提供类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.Xml;
namespace TEST
{
public class DomainService : IDomainService
{
public System.ServiceModel.Channels.Message ProvidePolicyFile()
{
XmlReader reader = XmlReader.Create("clientaccesspolicy.xml");
System.ServiceModel.Channels.Message result = Message.CreateMessage(MessageVersion.None, "", reader);
return result;
}

}

[ServiceContract]

public interface IDomainService
{
[OperationContract]
[WebGet(UriTemplate = "/clientaccesspolicy.xml")]
System.ServiceModel.Channels.Message ProvidePolicyFile();
}
}


   3.自托管 启动跨域访问

//启动跨域访问
ServiceHost crossDomainserviceHost = new ServiceHost(typeof(DomainService));
crossDomainserviceHost.AddServiceEndpoint(typeof(IDomainService), new WebHttpBinding()
, "http://127.0.0.1:4514/");

crossDomainserviceHost.Description.Endpoints[0].Behaviors.Add(new WebHttpBehavior());
crossDomainserviceHost.Open();


注:

优点:跨域访问的返回文件类型是:Content-Type: application/xml 。IE,Chrome都测试过,都可以使用。

缺点:客户端过多可能对造成过多的IO请求,需要做多客户端压力测试。

 方案2:

   1.在项目中加入clientaccesspolicy.xml,编译生成嵌入资源

    2.[b]加入域提供类[/b]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.Xml;
namespace Test
{
public class DomainService : IDomainService
{
public Stream ProvidePolicyFile()
{

var policyfile = "Test.clientaccesspolicy.xml";
Stream result= Assembly.GetExecutingAssembly().GetManifestResourceStream(policyfile);

return result;
}
}

[ServiceContract]

public interface IDomainService
{
[OperationContract]
[WebGet(UriTemplate = "/clientaccesspolicy.xml")]
Stream ProvidePolicyFile();

}
}


     3.自托管 启动跨域访问

注:

优点:没有过多的IO请求。

缺点:[b]跨域访问的返回文件类型是:Content-Type: application/octet-stream 。IE可用,Chrome不可用。[/b]

[b]   [b] 方案3:
[/b][/b]

  1.[b]加入域提供类[/b]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.Xml;
namespace TEST
{
public class DomainService : IDomainService
{
public Stream ProvidePolicyFile()
{
string clientAccessPolicy = "<?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 StringToStream(clientAccessPolicy);
}

private Stream StringToStream(string result)
{
WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";

return new MemoryStream(Encoding.UTF8.GetBytes(result));
}

}

[ServiceContract]

public interface IDomainService
{
[OperationContract]
[WebGet(UriTemplate = "/clientaccesspolicy.xml")]
Stream ProvidePolicyFile();

}
}


     3.自托管 启动跨域访问

注:

优点:没有过多的IO请求。[b][b]跨域访问的返回文件类型是Content-Type: application/xml[/b]。IE,Chrome可用[/b]

缺点:指定了编码方式,可能带来局限性。

总结:

方案3,1一般情况均较好。个人喜欢第3种。

--Domain--
  ServiceHost crossDomainserviceHost = new ServiceHost(typeof(DomainService));
  crossDomainserviceHost.AddServiceEndpoint(typeof(IDomainService), new WebHttpBinding()
     , "http://localhost:9090/");

  crossDomainserviceHost.Description.Endpoints[0].Behaviors.Add(new WebHttpBehavior());
  crossDomainserviceHost.Open();

  --Service--

  ServiceHost testHost = new ServiceHost(typeof(WCFService), new Uri("http://localhost:9090/WCFService/"));
  testHost.AddServiceEndpoint(typeof(IWCFService), new BasicHttpBinding()
    , "");

  ServiceMetadataBehavior bb = new ServiceMetadataBehavior();
  bb.HttpGetEnabled = true;
  bb.HttpGetUrl = new Uri("http://localhost:9090/WCFService/mex");
  testHost.Description.Behaviors.Add(bb);

  ServiceCredentials credential = new ServiceCredentials();
  testHost.Description.Behaviors.Add(credential);

  testHost.Open();

注意:请用“http://localhost:9090/WCFService/mex”来寻找服务,目前水平有限,还不能直接通过代码实现和配置一样通过http://localhost:9090/WCFService/"来寻找服务。望大家知道的能回复答案。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: