.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:N120112001
出刊日期:2012/01/11
本文將探討下一版的Visual Studio 11提供的新功能,特別是WCF Web API的應用與開發,讓你更容易設計RESTful類型的WCF服務。由於本文撰寫時使用的工具是Visual Studio 11 Developer Preview,而WCF Web API 則是Preview 6版,因此本文探討的內容在正式版上市時可能不適用。
在.NET Framework 3.5版已經為WCF提供REST(Representational State Transfer)架構的支援,.NET Framework4.5新增WCF Web API,同樣可以善用HTTP協定(使用GET、POST…等動詞),讓服務的開發動作變得更為簡單,您可以把REST視為下一代的分散式應用程式開發技術。
在RESTful的架構中,通常透過URI來存取服務端的資源,URI用來識別網路上的資源。URI通常會包含許多參數指明要取回的資源。參數通常以查詢字串(QueryString)的型式存在,有時也會內嵌在URL中。
RESTful模型的特色為:
- 支援多種資料格式,如SOAP、XML、JSON、資料串流、圖型資料或文字。
- 能夠使用HTTP通訊協定來傳送、接收POX訊息。
- 能夠剖析以及處理URI。
- 支援利用HTTP Get、POST、Delete等動詞的呼叫。
WCF Web API是一組Windows Communication Foundation (WCF)元件,以WCF為基礎而設計的,支援HTTP的GET、POST、DELETE動詞,自動處理底層HTTP傳輸協定的細節來簡化程式開發,並提供擴充的功能,在必要時讓程式設計師自行擴充它的功能。
本文將介紹如何使用Visual Studio 11 Developer Preview版本搭配WCF Web AIP來開發一個WCF服務,在服務端提供方法來讀取Employee資料後,回傳給用戶端應用程式顯示。
安裝NuGet Package Manager
NuGet Package Manager是一個免費、開放原始程式碼的Visual Studio外掛程式,可以簡化開發.NET應用程式時引用第三協力廠商函式庫的動作,讓開發更為容易。預設安裝Visual Studio 11 Developer Preview版本時,已經自動安裝NuGet Package Manager,請參考圖1所示。
圖 1:安裝NuGet Package Manager。
若要手動安裝,可以在Visual Studio 11 Developer Preview 選單「Tools」-「Extension Manager」開啟「Extension Manager」對話盒,點選左手邊「Online Extensions」選項後,在右上角文字方塊中輸入「NuGet Package Manager」字串來搜尋。找到此外掛程式之後,再按「Download」按鈕來下載並進行安裝的動作。
建立WCF服務專案
首先利用Visual Studio 11 Developer Preview建立一個WCF服務,為後續方便重複使用,我們選擇的是WCF Service Library專案。在Visual Studio 11 Developer Preview 「File」-「New Project」-「Visual C#」-「WCF」-「WCF Service Library」 ,設定名稱為「WCFWebLib」,然後按下「OK」按鈕,請參考圖2所示。
圖 2:建立WCF Service Library。
在「Solution Explorer」視窗,選取WCFWebLib項目,按滑鼠右鍵,從突顯式選單中,選取「Add」-「Class」,加入一個Employee類別,並宣告類別中包含兩個屬性,分別是int型別的EmployeeID屬性,以及string型別的EmployeeName屬性:
public class Employee {
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
}
按照相同的步驟,再加入一個新類別EmployeeRepository,類別中定義一個List<Employee>型別的變數:emps,用來存放員工資料。而EmployeeRepository類別的建構函式則建立三個Employee物件,並叫用Add方法,將物件加入List<Employee>集合:
public class EmployeeRepository
{
List<Employee> emps = new List<Employee>();
public EmployeeRepository()
{
Add(new Employee() { EmployeeID = 1, EmployeeName = "Mary" });
Add(new Employee() { EmployeeID = 2, EmployeeName = "Candy" });
Add(new Employee() { EmployeeID = 3, EmployeeName = "Judy" });
}
public void Add(Employee emp)
{
emps.Add(emp);
}
public void Delete(Employee emp)
{
emps.Remove(emp);
}
public List<Employee> GetEmployees()
{
return emps;
}
public Employee GetEmployeeById(int id)
{
return emps.Find((x) => x.EmployeeID == id);
}
}
EmployeeRepository類別中設計了Add與Delete方法,可以新增或移除集合中的Employee物件。GetEmployees方法用來回傳集合中所有的Employee資料;而GetEmployeeById可以利用id參數篩選出集合中符合篩選條件的Employee物件後回傳。
在「Solution Explorer」視窗,選取WCFWebLib項目,按滑鼠右鍵,從突顯式選單中,選取「Add Reference」,開啟「Add Reference」對話盒。「Add Reference」對話盒中有許多組件名稱以灰色方式顯示,這是因為預設的專案Target Framework為「.NET Framework 4.5 Client Profile」,不支援WCF的進階功能,因此組件便呈現灰色不啟用的狀態。在「Add Reference」對話盒中,雙擊以下組件:System.ServiceModel、System.ServiceModel.Activation與System.ServiceModel.Web。組件名字前方會出現一個黃色的驚探號,代表你必需將專案的Target Framework設定為「.NET Framework 4.5」才行,請參考圖3所示。
圖 3:參考組件。
當你按下「Add」按鈕將這三個組件加入參考後,Visual Studio 11 會自動將此專案的Target framework設定為「.NET Framework 4.5」,參考下圖所示:
圖 4:設定Target framework為「.NET Framework 4.5」。
在「Solution Explorer」視窗,選取WCFWebLib項目,按滑鼠右鍵,從突顯式選單中,選取「Manage NuGet Packages」,請參考圖5所示:
圖 5:「Manage NuGet Packages」。
接下來便會出現一個「Manage NuGet Packages」對話盒,在對話盒中左方選取「Online」,然後在右上方的文字方塊上輸入「Webapi」搜尋WebApi,請參考圖6所示:
圖 6:安裝Webapi。
選取WebApi項目上的「Install」按鈕進行安裝,請參考圖7所示。
圖 7:安裝Webapi。
接著便會出現一個授權的畫面,按下「I Accept」按鈕,請參考圖8所示。
圖 8:安裝授權。
安裝完成後,按「Close」按鈕結束「Manage NuGet Packages」對話盒,然後回到Visual Studio 11開發畫面。此時專案中會新增一個packages.config檔案,內含以下內容:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="HttpClient" version="0.6.0" />
<package id="JsonValue" version="0.6.0" />
<package id="WebApi" version="0.6.0" />
</packages>
設計WCF服務
設計支援WCF Web API的服務時,可以直接在服務類別上方套用ServiceContract Attribute,不需要先使用interface關鍵字定義合約。這種服務的類別也稱為資源類別(Resource Class)。當然在必要時,您也可以先定義合約,本文的範例便是採用此種作法。
預設當你建立WCF Service Library專案,專案中會包含一個IServices1.cs檔案,其中會有預設的範本程式碼,您可以刪掉預設的程式碼,加入以下定義,宣告一個IService1介面,介面中包含兩個方法:GetEmployees可以取回Employee物件組成的泛型集合;GetEmployeeByID方法可以取回EmployeeID屬性值符合傳入參數的Employee物件:
namespace WCFWebLib
{
[ServiceContract]
public interface IService1
{
[WebGet ( UriTemplate = "/employees" )]
[OperationContract]
List<Employee> GetEmployees ( );
[WebGet ( UriTemplate = "/employees/{id}" )]
[OperationContract]
Employee GetEmployeeByID ( int id );
}
}
GetEmployees與GetEmployeeByID方法上方套用WebGet Attribute,指明此方法可以透過HTTP GET動詞來進行呼叫。UriTemplate參數則是定義要叫用此方法時,所需使用的URL。而「{id}」代表的便是參數的意思,它會自動繫結到GetEmployeeByID方法中與其同名的id參數。
接著我們在Service1.cs檔案中撰寫Service1類別,實作IService1介面中的GetEmployees與GetEmployeeByID方法,其中GetEmployeeByID方法在找不到符合篩選條件的Employee物件時,便丟出HttpResponseException例外錯誤:
namespace WCFWebLib
{
public class Service1 : IService1 {
static EmployeeRepository Store = new EmployeeRepository ( );
public List<Employee> GetEmployees ( )
{
return Store.GetEmployees ( );
}
public Employee GetEmployeeByID ( int id )
{
Employee emps = Store.GetEmployeeById ( id );
if ( emps == null )
{
throw new HttpResponseException ( HttpStatusCode.NotFound );
}
return emps;
}
}
}
建立WCF裝載程式
在這篇文章中,採用最簡單的方式來裝載WCF應用程式。因此在目前的方案中加入Console應用程式,從Visual Studio 11 「File」-「Add」-「New Project」選取「Console Application」,命名為「ConsoleHost」。
下一個動作便是加入服務組件的參考。在「Solution Explorer」視窗,選取ConsoleHost項目,按滑鼠右鍵,從突顯式選單中,選取「Add Reference」,開啟「Add Reference」對話盒。選取「Solution」-「Projects」-選取「WCFWebLib」,請參考圖9所示:
圖 9:專案參考。
此外此專案也需要加入System.ServiceModel、System.ServiceModel.Activation與System.ServiceModel.Web三個組件的參考。在「Solution Explorer」視窗,選取ConsoleHost項目,按滑鼠右鍵,從突顯式選單中,選取「Add Reference」,開啟「Add Reference」對話盒。雙擊以下組件:System.ServiceModel、System.ServiceModel.Activation與System.ServiceModel.Web。
ConsoleHost專案也需要安裝WebApi。在「Solution Explorer」視窗,選取ConsoleHost項目,按滑鼠右鍵,從突顯式選單中,選取「Manage NuGet Packages」-「Install」。
接著我們在Main方法中加入以下程式碼,裝載WCF服務:
namespace ConsoleHost
{
class Program
{
static void Main ( string [ ] args )
{
var host = new HttpServiceHost (
typeof ( Service1 ) , "http://localhost:8000/api/" );
host.Open ( );
Console.WriteLine ( "Service is running..." );
Console.ReadLine ( );
}
}
}
HttpServiceHost類別定義在 Microsoft.ApplicationServer.Http命名空間之下,建立HttpServiceHost物件時,從建構函式傳入服務的型別,以及接聽的URI位置。範例中的「http://localhost:8000/api/」是服務的基礎位置。最後再叫用Open方法開始監聽8000埠是否有請求傳入。
測試
裝載程式設計完成之後,我們可以先利用瀏覽器才進行測試。從「Solution Explorer」視窗,選取ConsoleHost項目,按滑鼠右鍵,從突顯式選單中,選取「Set as Startup Project」。然後按F5執行,待主控台程式執行後,開啟瀏覽器,輸入以下URL位置叫用服務:
http://localhost:8000/api/employees
服務執行完的結果將會顯示在瀏覽器上,參考下圖所示。
圖 10:測試使用HTTP Get叫用服務。
若在瀏覽器上輸入以下URL,便可以查詢2號員工的資料:
http://localhost:8000/api/employees/2
服務執行完的結果請參考下圖所示。
圖 11:使用Http Get叫用服務GetEmployeeByID方法。
設計用戶端應用程式
WCF Web API新增一個HTTPClient類別來傳送HTTP請求,以及接收HTTP回應。並設計了HTTPRequestMessage與HttpResponseMessage類別來代表HTTP請求與回應的訊息。
最後我們寫了一個Console應用程式來叫用WCF服務。在目前的方案中加入Console應用程式,從Visual Studio 11 「File」-「Add」-「New Project」選取「Console Application」,命名為「ConsoleClient」。
在「Solution Explorer」視窗,雙擊ConsoleClient下的Properties項目,開啟專案屬性視窗。將專案的Target Framework設定為「.NET Framework 4.5」,請參考圖12所示。
圖 12:設定Target Framework為「.NET Framework 4.5」。
ConsoleClient專案也需要安裝WebApi。在「Solution Explorer」視窗,選取ConsoleClient項目,按滑鼠右鍵,從突顯式選單中,選取「Manage NuGet Packages」-「Install」,安裝WebApi。
下一個動作便是加入服務組件的參考。在「Solution Explorer」視窗,在ConsoleClient項目上,按滑鼠右鍵,從突顯式選單中,選取「Add Reference」,開啟「Add Reference」對話盒。選取「Solution」-「Projects」-選取「WCFWebLib」,請參考圖13所示。
圖 13:加入服務組件參考。
在ConsoleClient應用程式的Main方法中加入以下方法利用HttpClient的GetAsync方法以非同步的方式來呼叫服務GetEmployeeByID方法,取回特定員工編號的姓名:
class Program
{
static void Main ( string [ ] args )
{
HttpClient client = new HttpClient ( );
client.BaseAddress = new Uri ( "http://localhost:8000/ api/" );
Console.WriteLine ( "請輸入員工編號 : " );
string uri = " employees/" + Console.ReadLine ( ).Trim ( );
client.GetAsync ( uri ).ContinueWith ( r =>
{
r.Result.Content.ReadAsAsync<Employee> ( ).ContinueWith ( b =>
{
Employee emp = ( Employee ) b.Result;
Console.WriteLine ( emp.EmployeeName );
} );
} );
Console.WriteLine ( "Press [enter] to quit." );
Console.ReadLine ( );
}
}
取回服務資料後,叫用HttpContent的ReadAsAsync方法將結果取出後,印出員工的名稱。
設定同時執行ConsoleHost與ConsoleClient兩個專案,先執行ConsoleHost,再執行CosoleClient。在「Solution Explorer」視窗,Solution項目上,按滑鼠右鍵,從突顯式選單中,選取「Properties」,開啟專案屬性頁,設定「Multiple startup projects」,將ConsoleHost與ConsoleClient的Action設定為「Start」。要注意順序,ConsoleHost要出現在ConsoleClient項目的上方,請參考圖14所示。
圖 14:設定同時執行ConsoleHost與ConsoleClient兩個專案。
按F5同時執行兩個專案,參考以下執行結果,當你輸入員工編號2時,便可以印出他的名稱,請參考圖15所示。
圖 15:測試ConsoleClient叫用服務。
若要叫用服務的GetEmployees方法,取得所有員工資料,可以改寫ConsoleClient的Main方法如下:
static void Main ( string [ ] args )
{
HttpClient client = new HttpClient ( );
client.BaseAddress = new Uri ( "http://localhost:8000/api/" );
client.GetAsync ( "employees" ).ContinueWith ( r =>
{
r.Result.Content.ReadAsAsync<List<Employee>> ( ).ContinueWith ( b =>
{
List<Employee> emps = ( List<Employee> ) b.Result;
foreach ( var item in emps )
{
Console.WriteLine ( item.EmployeeName );
}
} );
} );
Console.WriteLine ( "Press [enter] to quit." );
Console.ReadLine ( );
}
總結
ASP.NET Web Service(*.asmx)與Windows Communication Foundation (簡稱WCF)底層都是以SOAP為基礎來啟用遠端程序呼叫 (Remote Procedure Call)。而WCF Web API可以讓程式設計師在網際網路上以HTTP協定,讓用戶端程式直接存取應用程式、資料以及服務。用戶端程式可以是瀏覽器、行動裝置上的應用程式,或桌上型電腦上的程式,甚至是其它的服務。WCF Web API可以支援XML、JSON以及OData 等資料格式。
參考資料
l WCF Web API Overview
http://wcf.codeplex.com/wikipage?title=WCF%20HTTP