部署您的WCF服務

承前文建立您的第一個WCF服務(跟著PluralSight的Aaron Skonnard一起作)建立您的第一個WCF服務(跟著piggy一起作),我們已成功建立WCF,接下來要host到IIS上作為後續使用!

piggy該篇重點在展現WCF主要步驟,大部分採用微軟預設的內容,沒有著墨「編輯WCF組態」的步驟,很多需要手動編輯的地方也無須更改,為了完整瞭解部署過程,本文將承接Aaron Skonnard說明發佈至IIS的完整流程。
  1. 對方案right click加入新網站

  2. 把新網站預設提供的IService.vb與Service.vb刪除
    因為我們已經在前文實作服務了~不需要這些東西!(這2個檔案在網站的App_Code資料夾裡)

  3. 對網站right click選擇加入參考
    加入後BIn資料夾會多出前文建立之服務的DLL檔案


  4. 要在網站中host我們的服務,要先configure svc檔案(這邊我把Service.svc改成eval.svc)
    原始碼:<%@ ServiceHost Language="VB" Debug="true" Service="Service" CodeBehind="~/App_Code/Service.vb" %>
    修改後:<%@ ServiceHost Language="VB" Debug="true" Service="EvalServiceLibrary.EvalServiceLibrary.EvalService" %>
    上面的修改是告訴網站我們的服務在哪,並且把不必要的CodeBehind刪除,因為我們的服務已經在前文實作了!

  5. 對網站的web.config right click編輯WCF組態
    將服務的Name指向自建的Eval服務(請指向新網站Bin資料夾內的dll)

    更改端點,將wsHttpBinding的Contract重新指向服務


    新增端點,Address給予basic同上一樣重新指向服務
  6. 刪除web.config中不需要的部分
    從< configSections >.....到< / system.webServer >都刪掉!

  7. eval.svc right click選「在瀏覽器中檢視」

    那要怎麼測試呢?
    可以利用「Visual Studio 2008 命令提示字元」,輸入wcftestclient 加上前圖的完整服務網址(以本文為例是http://localhost:2230/EvalServiceSite/eval.svc),將會自動開啟WCF測試用戶端視窗提供您測試!
    Visual Studio 2008 命令提示字元
    WCF測試用戶端

  8. 至IIS建立名為evalservicesite的虛擬目錄,並將路徑指向新網站的根目錄
  9. 在IIS中對eval.svc right click選擇瀏覽,瀏覽器將會開啟一個和第7步驟一樣的服務
    這邊特別注意的是,步驟7是以http://localhost:2230/EvalServiceSite/eval.svc有包含port的方式開啟,本步驟的http://localhost/EvalServiceSite/eval.svc已經不用port了!因為他確實是部署到本機的IIS上!!


  10. 同步驟6使用Visual Studio 2008 命令提示字元,開啟WCF測試用戶端視窗提供您測試!
搞定收工!

在Silverlight中透過WCF&LINQ使用SQL

針對Silverlight開發者常遇到binding SQL應用,提出循序漸進的範例,其中包含WCF與LING這兩種技巧,原文請參考Displaying SQL Database Data in a DataGrid using LINQ and WCF,本文步驟title依照原文,除了不同處會額外說明,步驟內容只提供操作方式的中文,需瞭解更詳細說明與操作意義者請參考原出處。
  1. Getting Started
    新增一Silverlight專案,命名為SqlData,為了後續使用WCF,我們需要Silverlight Project和Server Project,專案類型請選ASP.NET Web應用程式專案(ASP.NET Web Application Project)



  2. Examining the Two Projects
    VS2008會在名為SqlData的方案下為您新增2個project


    您的SQLDataTestPage.aspx將會自動以ScriptManager裝載未來的xaml以進行測試,如下圖。如果像piggy一樣已安裝Silverlight 3 Tool for VS2008的朋友,你的*.aspx會長的和*.html一樣,這邊不用擔心~只是描述的方式不同罷了,您還是可以改成以前Silverlight 2預設的裝載模式(使用ScriptManager)。可參考本狀況的詳細描述


  3. Linq To Sql
    對Server Project(SqlData.Web)按右鍵加入新項目,選擇「LINQ to SQL類別」


  4. 打開伺服器總管(Server Explorer)找到資料庫AdventureWorks    

    將Customers資料表直接拖曳到DataClasses1.dbml頁面




  5. Make the resulting LINQ class Serializable
    滑鼠左鍵在DataClasses1.dbml空白處按一下,接著至右側屬性視窗更改序列化模式(Serialization Mode),將無(None)改為單向(Unidirectional)


  6. Create the Web Service
    對SqlData.Web按右鍵加入新項目,選擇「有Silverlight功能的WCF服務」,此時專案終獲多2個新檔案Service1.svc以及Service1.svc.vb


    下預設的DoWork方法改成我們設計的新方法,新方法將利用TerritoryID取回該客戶的所有資料,新方法的完整代碼如下
        Function GetCustomersByTerritoryID(ByVal territoryId As Integer) As List(Of Customer)
            Dim db As New DataClasses1DataContext
            Dim matchingCustomers = From cust In db.Customer _
                                    Where cust.TerritoryID.Equals(territoryId) _
                                    Select cust
            Return matchingCustomers.ToList()
        End Function

  7. LINQ Syntax
    不瞭解何謂LINQ者請參照原文p11或其他更深入的書籍

  8. Watch Out for the Binding!(超重要)
    WCF在web.config預設binding是使用wsHttpBinding
    < services >
    < service behaviorConfiguration="SqlData.Web.Service1Behavior"
                    name="SqlData.Web.Service1" >
          < endpoint address="" binding="customBinding" bindingConfiguration="customBinding0" contract="SqlData.Web.Service1" />
          < endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    < /service >
    < /services >

    但是Silverlight只支援basic binding (例如SOAP 1.1),,需要手動更改binging!
    < services >
    < service behaviorConfiguration="SqlData.Web.Service1Behavior"
                    name="SqlData.Web.Service1">
          < endpoint address="" binding="basicHttpBinding" contract="SqlData.Web.Service1" />
          < endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    < /service >
    < /services >

    OK!我們的服務已經架設好勒!

  9. Creating the Silverlight Application
    對Silverlight Application(SqlData)的參考按右鍵,選擇「加入服務參考」


    加入服務參考視窗出現後,按下搜尋(Discover)並選擇「方案中的服務」,我們新建的服務將會被找到,服務中的GetCustomersByTerritoryID也可以一併察看。


    選擇Service1按下確定,之後就可以透過這個參考去存取服務。


  10. Creating the XAML
    接下來設計一個簡單的UI,包含2個row,第1個用來放使用者輸入的TerritoryID,第2個放查詢結果。首先配置容器Grid的layout,xaml碼如下

        < Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True">
            < Grid.RowDefinitions>
                < RowDefinition Height="10" />
                < RowDefinition Height="50" />
                < RowDefinition Height="*" />
                < RowDefinition Height="10" />
            < /Grid.RowDefinitions>
            < Grid.ColumnDefinitions>
                < ColumnDefinition Width="10" />
                < ColumnDefinition Width="*" />
                < ColumnDefinition Width="10" />
            < /Grid.ColumnDefinitions>
        < /Grid>

    使用Expression Blend 3開啟xaml將會看到下圖成果,總共有3個row、2個column,邊邊都是為了版面故意規劃的row&column,主要是下圖2個大塊的row,如果用VS2008設計檢視看不到或看到的layout很怪的話,請用Blend 3來make sure



  11. Placing controls in the top row
    在第1個row準備放入3個控制項—Textblock、TextBox、Button,為了快速配置3個控制項於row1,我們採用stack panel,然後用border來框住這個範圍

    < Border BorderBrush="Black" BorderThickness="2" Grid.Row="1" Grid.Column="1"/>
    < StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
    < TextBlock Text="Last name to search for: " VerticalAlignment="Bottom" FontSize="18" Margin="15,0,0,0" />
        < TextBox x:Name="LastName" Width="250" Height="30" Margin="2,0,0,4" VerticalAlignment="Bottom"/>
        < Button x:Name="Search" Width="75" Height="30" Margin="20,0,0,4" Content="Search" VerticalAlignment="Bottom" Background="Blue" FontWeight="Bold" FontSize="14" />
    < /StackPanel>


    在第2個大塊的row放一個DataGrid

    < data:DataGrid x:Name="theDataGrid_" Margin="40,15" Grid.Column="1" Grid.Row="2" Width="700" Height="500" d:LayoutOverrides="GridBox"/>

    介面設計完成!

  12. Write the Event Handler for the Search Button
    我們希望UI中的Button被按下去之後會執行查詢的動作(搜尋和Text Box具有相同TerritoryID的顧客),所以要開始在*.xaml.vb撰寫程式碼

    Private Sub Page_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            AddHandler Search.Click, AddressOf Search_Click
    End Sub

    'Write the Event Handler for the Search Button
    Private Sub Search_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    Dim webService As ServiceReference1.Service1Client = New ServiceReference1.Service1Client()
       AddHandler webService.GetCustomersByTerritoryIDCompleted, AddressOf webService_GetCustomersByTerritoryIDCompleted
       '注意:從Silverlight呼叫服務只能用非同步(Asynchronously)的方式
        webService.GetCustomersByTerritoryIDAsync(TerritoryID.Text)
    End Sub

    Private Sub webService_GetCustomersByTerritoryIDCompleted(ByVal sender As Object, ByVal e As SqlData.ServiceReference1.GetCustomersByTerritoryIDCompletedEventArgs)
    theDataGrid.ItemsSource = e.Result
    End Sub

    當然是件處理常式撰寫完畢後,要記得指派給Button,所以請在其屬性加上Click="Search_Click"

  13. 測試
    build成功後,輸入3搜尋(TerritoryID是Integer型別),可即刻取得ID為3的顧客資料。


    ★參考網址
    原出處
    下載AdventureWork資料庫
    本文使用的AdventureWork資料庫(搭配SQL Server Express 2005)

Count不是System.Array的成員

今天把A網站整個copy到B網站之下
想說做單一簽入/出比較方便,測試結果一切正常,可是卻發現A網站其中一支放到B之後報錯
錯誤訊息:'Count'不是'System.Array'的成員。

查了一下發現有人遇到一樣的問題,解決方法是改成使用Length而非Count
令人納悶的是A網站卻可使用String().Count,參考網站中的Pilot兄也跟我遇到一樣的問題,原因為何就不得而知勒XD

DELL螢幕

這次採購選擇跟家裡一樣的BENQ G2220HD
無奈笨Q說不出這台(謎之聲:其實是公司採購資訊太lag)
可是又不想換其他只有D-Sub的型號,這樣一來只剩10,000的DELL和26,5000的EZIO可選,
心裡暗暗OS:賺到了賺到了!沒用過DELL說^0^

可惜還是被CC退回,叫我們改用3隻鳥VX2233WM,阿~希望3隻鳥這款爭氣一點,重新贏回我的心~
不然之前IGIS用3隻鳥爽度實在很差╰●-●╯

建立您的第一個WCF服務(跟著piggy一起作)

寫在前面:相較於前文piggy在本文將提供最精簡的步驟,盡量保持專案初始的配置(例如直接使用WCF專案預設提供的Service.vb和IService.vb檔案)

情境描述:建立一個簡單的服務,服務提供的資料具備3種屬性,而服務提供的方法則有遞交、取得、刪除3種方法。
a)屬性命名:Id、Sumbitter、Comments
b)方法命名:SubmitEval、GetEvals、RemoveEval

1.新增專案

建立名為EvalServiceLibrary2的WCF服務程式庫


專案的預設配置

2.定義服務(本步驟在IService1.vb進行)
a)ServiceContract
將預設的2個方法刪除(GetData、GetDataUsingDataContract),加入我們設計的3種方法(SubmitEval、GetEvals、RemoveEval)

 原始ServiceContract


加入3個新方法的ServiceContract

上圖的Eval型別錯誤不用擔心,那是因為我們還沒規範出自定義的Eval型別!
步驟a已完成服務的method,接下來我們要定義DataContract,明確規範自定義的Eval型別!
b)DataContract

原始DataContract


在DataContract規範自定義之Eval Class

3.實作服務(本步驟在Service1.vb進行)
將預設2個方法的實作部分刪除,利用IntelliSense在Implements IService1後面按下Enter,VS2008將自動加入需要實作的code片段,這些片段是根據步驟2我們定義的3種方法所產生。

 原始Service1.vb


根據步驟2 Contract自動產生的新Service1.vb

繼續撰寫3個方法(IntelliSense自動產生的)的內容,完成實作的部分,此時錯誤清單已經沒有任何錯誤!WCF服務已建置成功!

實作內容

3.F5進行測試(測試請參考前一篇步驟14&15)

4.存檔

建立您的第一個WCF服務(跟著PluralSight的Aaron Skonnard一起作)

1.開啟VSTS2008,專案→新增專案→WCF→WCF服務程式庫→輸入名稱EvalServiceLibrary

2.刪除預設的IService1.vb與Service1.vb

3.對專案EvalServiceLibrary按右鍵→加入→類別→輸入名稱Eval

4.在Eval.vb輸入程式碼
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Runtime.Serialization

Namespace EvalServiceLibrary
    < DataContract() > _
    Public Class Eval
        < DataMember() > _
        Public Id As String
        < DataMember() > _
        Public Submitter As String
        < DataMember() > _
        Public Comments As String
    End Class
End Namespace


5.同步驟3再新增1個類別IEvalService.vb,貼上程式碼如下
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Runtime.Serialization

Namespace EvalServiceLibrary
        < ServiceContract() > _
    Public Interface IEvalService
        < OperationContract() > _
        Sub SubmitEval(ByVal eval As Eval)
       
< OperationContract() > _
        Function GetEvals() As List(Of Eval)
       
< OperationContract() > _
        Sub RemoveEval(ByVal id As String)
    End Interface
End Namespace
 

 6.再次新增新類別EvalService.vb並輸入下列程式碼
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text

Namespace EvalServiceLibrary
    Public Class EvalService
    End Class
End Namespace

7.在 Public Class EvalService後面輸入:Implements .NET 的IntelliSense會自動出現各種namespace供你選取,選擇IEvalService後頁面會自動放置你需要實做的各類Interface,也就是步驟5我們所設計的3種[OperationContract]


8. 承前,在Public Class EvalService : Implements IEvalService前輸入
完整程式碼如下highlight
Namespace EvalServiceLibrary
    < ServiceBehavior(InstanceContextMode:=InstanceContextMode.Single) > _
    Public Class EvalService : Implements IEvalService

9.把EvalService.vb的三個method完成後進行偵錯,完整程式碼如下highlight
Public Class EvalService : Implements IEvalService

        Dim evals As New List(Of Eval)()
        Public Function GetEvals() As System.Collections.Generic.List(Of Eval) Implements IEvalService.GetEvals
            Return evals
        End Function

        Public Sub RemoveEval(ByVal id As String) Implements IEvalService.RemoveEval
            evals.Remove(evals.Find(Function(e) e.Id.Equals(id)))
        End Sub

        Public Sub SubmitEval(ByVal eval As Eval) Implements IEvalService.SubmitEval
            eval.Id = Guid.NewGuid().ToString
            evals.Add(eval)
        End Sub
    End Class

10.對App.config按右鍵選擇「編輯WCF組態」


11.點選服務EvalServiceLibrary.Service1,右方視窗出現服務的一般屬性

12.承上繼續修改Name屬性,瀏覽至方案資料夾下的bin\Debug\EvalServiceLibrary.dll,指向型別名稱EvalServiceLibrary.EvalServiceLibrary.EvalService的服務類型

13. 在左側視窗展開服務的端點(endpoint),開始修改端點內容的Contract屬性,一樣瀏覽至bin\Debug\EvalServiceLibrary.dll,指向型別名稱EvalServiceLibrary.EvalServiceLibrary.IEvalService的合約類型

第2個端點則不用修改,回到最上層的服務觀看所有服務端點,可以發現第2個的Contract是「IMetadataExchange」,它是負責runtime時取回服務的metadata

14.存檔後按下F5,出現「WCF測試用戶端」視窗

同時Windows工具列右下方會出現1個可愛的WCF服務主機icon,滑鼠double-click開啟WCF服務主機可以察看服務的address等metadata

15.開始透過WCF測試用戶端進行測試
a)SubmitEval測試
  • double-click視窗左側的SubmitEval,於右方開啟測試窗格
  • 在Comment與Submitter輸入任意字串
  • 按下叫用(Invoke)完成測試
  • 重複上述步驟做3次測試
b)GetEvals測試
  • double-click視窗左側的GetEval,於右方開啟測試窗格
  • 按下叫用 ,可以看到SumbitEval送出的3筆資料
c)RemoveEval測試
  • 挑選GetEval中列出的其中一筆資料,複製其Id
  • double-click視窗左側的RemoveEval,於右方開啟測試窗格
  • 將複製的Id貼入進行測試(貼入前記得移掉雙引號)
  • 按下叫用,完成測試
  • 再回去GetEvals並重新叫用,發現被移除1筆資料,只剩下2筆
16.結束

★本篇依據Windows Communication Foundation 初學者指南第一段影片實做,重點是提供詳細中文步驟,嫌步驟太繁雜or想知道操作意義者,請參考piggy精簡後的建立您的第一個WCF服務(跟著piggy一起作)