WCF服务以控制台程序为宿主时的跨域访问问题(附源码)

来源:互联网 发布:淘宝全屏店招尺寸 编辑:程序博客网 时间:2024/05/22 00:51

     

      前几天研究SilverLight时碰到了这个问题,本以为很轻松的试验结果很不顺利,查了很多资料才解决了这个问题,在此把解决问题的方法写出来,也方便其它朋友借鉴。

 

      问题是这样产生了,我在测试SilverLight时为了测试与WCF的通讯,创建了一个控制台的应用程序做为WCF服务的宿主程序。

 

     同时创建了一个SilverLight应用程序和一个承载SilverLight的Web程序.

 

     解决方案如图:

   

 

 

   控制台程序:

 

   1.添加 WCF服务

 

     命名为WCFService.cs,并添加服务,代码如下:

 

namespace WCFBase
{
    // 注意: 如果更改此处的类名 "WCFService",也必须更新 App.config 中对 "WCFService" 的引用。
    public class WCFService : IWCFService
    {
        public int DoWork(int a,int b)
        {
            return a + b;
        }

        public int DoWork2(int a, int b)
        {
            return a - b;
        }
    }
}

 

 

系统会自动添加App.config文件和相关配置节信息

 

内容如下:

 

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
        <behaviors>
            <serviceBehaviors>
                <behavior name="WCFBase.WCFServiceBehavior">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
         </behaviors>
      
        <services>
            <service behaviorConfiguration="WCFBase.WCFServiceBehavior" name="WCFBase.WCFService">
                <endpoint address="" binding="basicHttpBinding" contract="WCFBase.IWCFService">
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:9090/WCFService/" />
                    </baseAddresses>
                </host>
            </service>
            </services>
     
    </system.serviceModel>
 
</configuration>

 

2.加载WCF服务

 

打开主程序入口Main方法,代码如下

 

namespace WCFBase
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost host = new ServiceHost(typeof(WCFService));
            host.Open();

 

            Console.WriteLine("I'am Here.");
            Console.ReadKey();
            host.Close();


        }
    }
}

 

至此运行该控制台程序,WCF服务启可使用。

 

 

但当垮域访问时会运行错误,提示没有仅限操作。这时需要如下操作

3.使WCF可以垮域访问

 

   A.在控制台程序根目添加clientaccesspolicy.xml文件

   内容如下:

 

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

 

 

   B.添加接口 IDomainService (名称可自定义)

 

 首先要添加System.ServiceModel.Web 引用

代码如下:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.ServiceModel;
using System.ServiceModel.Channels;

 

namespace WCFBase
{
    /**/
    /// <summary>
    /// 跨域访问策略服务接口
    /// 注意:如果你更新了ICrossDomainService接口,需要同时更新App.Config
    /// </summary>
    [ServiceContract]
    public interface IDomainService
    {
        [OperationContract]
        [WebGet(UriTemplate = "ClientAccessPolicy.xml")]
        Message ProvidePolicyFile();
    }
}

 

C.实现接口IDomainService

类:DomainService(可自定义)

代码如下:

    

namespace WCFBase
{
    public class DomainService:IDomainService
    {
        #region IDomainService 成员

        public System.ServiceModel.Channels.Message ProvidePolicyFile()
        {
             FileStream filestream = File.Open(@"ClientAccessPolicy.xml", FileMode.Open);
            // Either specify ClientAcessPolicy.xml file path properly
            // or put that in /Bin folder of the console application
            XmlReader reader = XmlReader.Create(filestream);
            System.ServiceModel.Channels.Message result = Message.CreateMessage(MessageVersion.None, "", reader);
           return result;
        }

        //CrossDomainServiceBehavior

        #endregion
    }
}

 

 

D.修改App.config文件

修改后为

 

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
        <behaviors>
            <serviceBehaviors>
                <behavior name="WCFBase.WCFServiceBehavior">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
          <endpointBehaviors>
            <behavior name="DomainServiceBehavior">
              <webHttp/>
            </behavior>
          </endpointBehaviors>
        </behaviors>
      

      
        <services>
            <service behaviorConfiguration="WCFBase.WCFServiceBehavior" name="WCFBase.WCFService">
                <endpoint address="" binding="basicHttpBinding" contract="WCFBase.IWCFService">
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:9090/WCFService/" />
                    </baseAddresses>
                </host>
            </service>
            <service name="WCFBase.DomainService">
                <endpoint address="" behaviorConfiguration="DomainServiceBehavior"
                    binding="webHttpBinding" contract="WCFBase.IDomainService" />
                <host>
                    <baseAddresses>
                        <add baseAddress="
http://localhost:9090/" />
                    </baseAddresses>
                </host>
            </service>
        </services>
     
    </system.serviceModel>
 
</configuration>

 

灰色区域为新添加的信息,还没有完成,继续...

 

E.修改控制台打开主程序入口Main方法

 

代码如下:

 

namespace WCFBase
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost host = new ServiceHost(typeof(WCFService));
            host.Open();

 

            ServiceHost crossDomainserviceHost = new ServiceHost(typeof(DomainService));
            crossDomainserviceHost.Open();

 

            Console.WriteLine("I'am Here.");
            Console.ReadKey();
            host.Close();


        }
    }
}

 

灰色区域为新添加代码

最终程序结构如下:

到此WCF服务即可实现垮域访问.

 

注意:需要将clientaccesspolicy.xml文件复制到 WCFBase.exe相同目录下。

 

 

4.SilverLight与WCF通讯测试

 运行控制台程序 WCFBase.exe

如图:

 

 

 

  在SilverLight程序中添加"服务引用",地址为http://localhost:9090/WCFService/

 

  SilverLight代码如下

 

private void btnTest_Click(object sender, RoutedEventArgs e)
        {
           ServiceReference1.WCFServiceClient wcf = new SilverlightApp.ServiceReference1.WCFServiceClient();
           wcf.DoWorkCompleted += new EventHandler<SilverlightApp.ServiceReference1.DoWorkCompletedEventArgs>(wcf_DoWorkCompleted);

           
            wcf.DoWorkAsync(1, 2);
        }

        void wcf_DoWorkCompleted(object sender, SilverlightApp.ServiceReference1.DoWorkCompletedEventArgs e)
        {
            MessageBox.Show(e.Result.ToString());
        }

 

 

   测试截图:

 

证明SilverLight可以正常调用WCF的DoWork方法,并正确返回结果。

 

源代码下载:

 

http://download.csdn.net/source/2014616

原创粉丝点击