本篇我們介紹Silverlight通過net.Tcp方式訪問IIS宿主的WCF。
Windows (Process) Activation Service (簡稱:WAS 全稱:Windows 進程激活服務)是 IIS7.0 特有的新增功能,比IIS6 的功能更加強大,它提供並支持除HTTP之外的更多協議。由於Net.tcp 協議在 Silverlight 中的不支持傳輸層安全性,我們盡量在安全性比較好的Intranet 環境中使用此傳輸方式。
本例子的開發環境是:Win7旗艦版+VS2010+Silverlight4+IIS7。項目代碼和結構和上一篇一樣,WCF服務代碼沒有任何改變,只不過是WcfHost.web 中的Web.Config 中配置代碼進行了改變,為了方便查看,我再貼一下項目結構和代碼:
項目結構(如圖):
代碼實現:
類庫LxContracts:(包括數據契約Student.cs和操作契約IStudent.cs)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.Runtime.Serialization; namespace LxContracts { [DataContract] public class Student { /// <summary> /// 學生編號 /// </summary> [DataMember] public int StuId { get; set; } /// <summary> /// 學生姓名 /// </summary> [DataMember] public string StuName { get; set; } /// <summary> /// 所在班級 /// </summary> [DataMember] public string ClassName { get; set; } /// <summary> /// 聯系電話 /// </summary> [DataMember] public string TelPhoneNum { get; set; } } }

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.Serialization; using System.ServiceModel; namespace LxContracts { [ServiceContract] public interface IStudent { [OperationContract] List<Student> GetStudent(); } }
類庫LxServices:( 改類庫包括一個模仿獲取數據庫集合類StudentList.cs和服務類StudentService.cs)

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LxContracts { public class StudentList:List<Student> { public StudentList() { this.Add(new Student() { StuId = 1, StuName = "小明", ClassName = "計算機一班", TelPhoneNum = "123456" }); this.Add(new Student() { StuId = 2, StuName = "小紅", ClassName = "計算機二班", TelPhoneNum = "234567" }); this.Add(new Student() { StuId = 2, StuName = "小蘭", ClassName = "計算機三班", TelPhoneNum = "890123" }); } } }

using System; using System.Collections.Generic; using System.Linq; using System.Text; using LxContracts; namespace LxServices { public class StudentService:IStudent { public List<Student> GetStudent() { //實際情況應該為從數據庫讀取 //本例手動生成一個StudentList StudentList ListStuent = new StudentList(); return ListStuent; } } }
站點WcfHost.web
站點WcfHost.web,這是一個Asp.net 空web應用程序。
1、右擊” WcfHost.web”—“添加”—“新建項”—“wcf服務”,命名為”StudentSrv.svc” 。如圖:
在項目中刪除”StudentSrv.svc.cs”文件和”IStudentSrv.cs”文件。右擊”StudentSrv.svc”文件,選擇”查看標記”,將代碼修改為:
<%@ ServiceHost Language="C#" Service="LxServices.StudentService" %>
2、修改webconfig 文件,代碼如下:(配置文件和第一篇http方式 發生了改變)

<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.0" /> </system.web> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="LxBehavior"> <serviceMetadata httpGetEnabled="false" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> <!--這個必須寫,Silverlight不支持具有安全性的 NetTcpBinding,寫了之后,客戶端引用就變成了CustomBinding--> <bindings> <netTcpBinding> <binding name="myTcpBinding"> <security mode="None" /> </binding> </netTcpBinding> </bindings> <services> <service name="LxServices.StudentService" behaviorConfiguration="LxBehavior"> <endpoint address="" binding="netTcpBinding" bindingConfiguration="myTcpBinding" contract="LxContracts.IStudent" /> <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> </service> </services> <!--關閉 ASP.NET 兼容性模式--> <serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" /> </system.serviceModel> <!--設置默認頁面為StudentSrv.svc--> <system.webServer> <defaultDocument> <files> <remove value="default.aspx" /> <remove value="iisstart.htm" /> <remove value="index.html" /> <remove value="index.htm" /> <remove value="Default.asp" /> <remove value="Default.htm" /> <add value="StudentSrv.svc" /> </files> </defaultDocument> </system.webServer> </configuration>
注意:(1) 配置文件中把 <serviceMetadata httpGetEnabled="false" /> 設置成了false;<service>節點中也去掉了 basicHttpBinding方式的Endpoint,目的是我們的服務元節點地址和傳輸方式只提供net.Tcp方式的。當然也可以不用去掉,這樣服務就提供兩種通道了。(2)netTcp方式 必須增加元數據發布節點mex,因此wcf的服務元數據地址就是:net.tcp://localhost:端口號/StudentSrv.svc/mex
部署服務:
1、添加必要的組件:
1)打開 “控制面板”—“程序和功能”—“打開或關閉Windows功能”。節點“Microsoft .Net Framework 3.5.1 ”下面的兩項WCF Http 激活和WCF No Http 激活都必須安裝。如下圖:
2)安裝IIS6兼容性和管理工具:
3)查看服務:確保服務Net.Tcp Listener Adapter、Windows Process Activation Service和World Wide Web Publishing Service 都已經啟動。
2、在IIS7中進行部署:
1)打開IIS7,右擊”應用程序池—“添加應用程序池。名稱輸入為:”WcfTcpPool”,Framework版本選擇為:4.0,如下圖:
2)右擊網站—“添加網站”;網站名稱為:WcfTcpWeb;應用程序池選擇我們剛剛創建的”WcfTcpPool”;物理路徑選擇我們項目下的WcfHost.web的所在路徑;http端口我選擇的是7070,如下圖:
3)選擇我們剛剛創建的網站,在IIS最右面的操作列表中,選擇”高級設置”;在”已啟用的協議” 中輸入 net.tcp ,每個協議之間用 逗號 分隔,如下圖:
4)為網站添加綁定:右擊WcfTcpWeb網站—“編輯綁定”,添加綁定,選擇”net.tcp” ,綁定信息輸入“4505:*”,如下圖:
注意:Silverlight 只能訪問介於4502至4534范圍之間的端口。
5)右擊我們的網站,選擇”管理網站”—“瀏覽”;瀏覽器會顯示如下信息:(我們的服務配置已經成功)
在Silverlight中進行調用:
1、為Silverlight程序添加WCF:
“右擊”—“SiverlightDemo”—“添加服務引用”—“輸入服務地址”net.tcp://localhost:4505/StudentSrv.svc/mex --點擊“前往”,就會找到服務,命名為”WCF.StudentSrv”后,點擊”確定”。
2、在Silverlight中調用WCF:(以下代碼跟第一篇實例一樣,為了查看方便我又貼了一下)
MainPage.xaml中添加”DataGrid”控件。

<sdk:DataGrid x:Name="dgStudnet" Grid.Row="0" AutoGenerateColumns="False"> <sdk:DataGrid.Columns> <sdk:DataGridTextColumn Header="學生編號" Width="80" Binding="{Binding StuId}" /> <sdk:DataGridTextColumn Header="學生姓名" Width="100" Binding="{Binding StuName}" /> <sdk:DataGridTextColumn Header="所在班級" Width="120" Binding="{Binding ClassName}" /> <sdk:DataGridTextColumn Header="電話號碼" Width="100" Binding="{Binding TelPhoneNum}" /> </sdk:DataGrid.Columns> </sdk:DataGrid>

namespace SilverlightDemo { public partial class MainPage : UserControl { ObservableCollection<Student> listStudent; public MainPage() { InitializeComponent(); listStudent = new ObservableCollection<Student>(); this.Loaded += new RoutedEventHandler(MainPage_Loaded); } void MainPage_Loaded(object sender, RoutedEventArgs e) { StudentClient proxyClient = new StudentClient(); proxyClient.GetStudentAsync(); proxyClient.GetStudentCompleted += new EventHandler<GetStudentCompletedEventArgs>(proxyClient_GetStudentCompleted); } void proxyClient_GetStudentCompleted(object sender, GetStudentCompletedEventArgs e) { if (e.Error == null) { listStudent = e.Result; this.dgStudnet.ItemsSource = listStudent; } } } }
3、運行:右擊 "SilverlightDemo" ,選擇“調試”--“啟動新實例”,會產生以下異常信息:
這還是跨域問題,怎么解決呢?當然還是需要跨域文件(clientaccesspolicy.xml)了,但這個跨域文件和上一篇http綁定方式的跨域文件內容有所不同,放置的位置也有所不同。

<?xml version="1.0" encoding="utf-8"?> <access-policy> <cross-domain-access> <policy> <allow-from http-request-headers="*"> <domain uri="*" /> </allow-from> <grant-to> <socket-resource port="4502-4534" protocol="tcp" /> <resource path="/" include-subpaths="true"/> </grant-to> </policy> </cross-domain-access> </access-policy>
但是這個跨域文件放到哪里呢?
netTcp方式的跨域文件並不是放到我們項目中宿主wcf的網站WcfHost.web的根目錄,而是放到IIS 80端口網站的根目錄。我計算機IIS下80端口的網站是Default Web Site,因此放到此網站根目錄下面:
再次運行我們的Silverlight 程序,會發現WCF調用成功,第一次運行有點慢,耐心等待一下,結果如下圖:
至此,本篇主要介紹了Silverlight和WCF基於net.tcp 方式傳輸的配置及說明,下一篇我們利用Silverlight和WCF實現一個全雙工通信的例子。