Sileverlight很多時候需要通過wcf和後臺,程式進行互動。如果 iis was託管還好,極端的遇到自託管的程式,console,windowsservice,winform,wpf等,就會出現跨域問題。網上很多解決方式。俺在以下博文基礎上又總結了點。
以下博文可以先學習下:
http://blog.csdn.net/boyhxy/article/details/5224112
http://blog.sina.com.cn/s/blog_74066ace0100vhs5.html
http://www.cnblogs.com/lxblog/archive/2012/08/02/2620393.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.加入域提供類
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請求。
缺點:跨域訪問的返回檔案型別是:Content-Type: application/octet-stream 。IE可用,Chrome不可用。
方案3:
1.加入域提供類
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請求。跨域訪問的返回檔案型別是Content-Type: application/xml。IE,Chrome可用
缺點:指定了編碼方式,可能帶來侷限性。
總結:
方案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/"來尋找服務。望大家知道的能回覆答案。