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


      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/"来寻找服务。望大家知道的能回复答案。

     

  • 相关阅读:
    双指针
    二分查找
    二叉树
    递归思想
    排序算法
    Java常用集合使用方法总结
    攻防世界-PHP文件包含
    正则表达式随笔
    ts 函数
    ts 联合类型
  • 原文地址:https://www.cnblogs.com/mephisto/p/3432139.html
Copyright © 2020-2023  润新知