WCF服務以控制台程式為宿主時的跨域訪問問題(附源碼)

來源:互聯網
上載者:User

     

      前幾天研究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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.