上方廣告

Lady Kukki 手作糖霜餅乾

2011年8月27日 星期六

Silverlight初探(三) - 使用WCF存取資料庫篇

本文要示範如何在Silverlight當中使用WCF,何謂WCF,簡單的說就是WebService,詳細說明請參閱本文下方連結,首先我先簡單的示範如何寫一個正常的WCF,我根據了Steven的心得筆記寫出了下面語法的WCF。
namespace WCFService
{
    [ServiceContract]
    public interface IHelloWord
    {
        //為每個 operation 指定唯一的別名,這樣就可以使用相同名稱的方法
        [OperationContract(Name = "MyHello")]
        string MyHello(string text);

        //為每個 operation 指定唯一的別名,這樣就可以使用相同名稱的方法
        [OperationContract(Name = "MyHello1")]
        int MyHello(int text);

        //沒有加上[OperationContact]的method,就不會成為合約的一部份。
        string MyOtherHello(string text);
    }

    class HelloWord : IHelloWord
    {
        public string MyHello(string text)
        {
            return "Hello " + text;
        }

        public int MyHello(int text)
        {
            MyOtherHello(text.ToString());
            return 0;
        }

        public string MyOtherHello(string text)
        {
            return "這個method非合約的部份,無法透過WCF呼叫!";
        }
    }
}
測試一下執行畫面正常(如下圖),可是使用Silverlight呼叫的時候卻出現【在 ServiceModel 用戶端組態區段中找不到參照合約 'ServiceReference1.IHelloWord' 的預設端點項目。可能是因為找不到應用程式的組態檔,或是用戶端項目中找不到符合此合約的端點項目。】(呼叫方式請參閱下面語法,但是前提必須將此WCF加入專案參考),網路Google一下原來WCF如果要給Silverlight讀取,使用方式是不相同的,必須啟用給ASP.NET專用的服務,由於這個項目啟用後會使Web.Config改變很多東西,我就不再解釋了,想要知道怎麼啟用此服務,可以參閱這個阿六仔的Blog。必須要啟用順便提一下,將此WCF掛到IIS下面去執行記得要把NET.Framework版本改成4.0,否則會出現【404 - 找不到檔案或目錄】。
// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    ServiceReference1.HelloWordClient proxy = new ServiceReference1.HelloWordClient();
    proxy.MyHelloCompleted += new EventHandler<servicereference1 .myhellocompletedeventargs="">(proxy_MyHelloCompleted);
    //以非同步方式呼叫WCF服務功能
    proxy.MyHelloAsync("Lawrence");
    proxy.CloseAsync();
}

void proxy_MyHelloCompleted(object sender, ServiceReference1.MyHelloCompletedEventArgs e)
{
    Dispatcher.BeginInvoke(delegate()
    {
        MessageBox.Show(e.Result);
    }); 
}


WCF的設定很多,會發生很多錯誤,但是這一開始接觸新的技術都會發生的事,相信把錯誤訊息拿去Google一下應該很快就會解開了,而且自己查過才更容易知道錯的原因,因此我就不再列舉我發生的錯誤了,到了這裡你應該已經可以讓Silverlight呼叫WCF了Method了,因此我們只需要在幾個步驟就可以完成我們的需求了,我們需要存取資料庫的資料,WCF方面的寫法就如同正常的Method,只是我們這次要把回傳的值改成DataSet,至於為什麼不使用DataTable?
想在WCF傳資料一定要有XmlSerialize的資料包裝動作,DataTabel 沒有包裝資料的能力,所以不能傳輸。DataSet 有包裝資料的能力,所以可以傳輸。
網路上有些人說WCF可以回傳DataTable型態的資料,只需要給DataTable命名即可,我本人試過是沒有成功,有興趣的人請自己嘗試吧。

最後一切都完成了,我卻發現一個重大的問題就是,我的WCF竟然不允許跨域存取【嘗試向 URI http://xxx 進行要求時發生錯誤。這可能是因為嘗試以跨網域方式存取服務,而沒有適當的跨網域原則所造成,或是由不適用於 SOAP 服務的原則所造成。您可能需要連絡服務的擁有者,以發佈跨網域原則檔案,並確定它允許傳送 SOAP 相關的 HTTP 標頭。這項錯誤也可能是在 Web 服務 Proxy 中使用內部型別而沒有使用 InternalsVisibleToAttribute 屬性所造成。如需詳細資訊,請查看內部例外狀況。】。好在有Google,一樣馬上找到解決辦法,只需要在網站根目錄加入已下兩支檔案(二擇一),還有拜託一下貼語法之前請先參考一下MSDN怎麼說的不要亂貼一通,安全性問題還是要注意。

clientaccesspolicy.xml
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="SOAPAction">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

crossdomain.xml
<cross-domain-policy>
  <allow-http-request-headers-from domain="*" headers="SOAPAction,Content-Type" />
</cross-domain-policy>

何謂WCF & 如何使用WCF
Steven的心得筆記
MSDN WCF線上教學