微軟在WCF 3.5中就通過提供基于Web HTTP的編程模式使我們很容易地創建基于REST的服務,WCF 4.0中對此進行了較大的改進。為了讓讀者對REST在WCF中的應用有一個大致的了解,我們先來進行一個簡單的實例演示。 [源代碼從這里下載]
一、定義服務契約
在這個實例中,我們創建一個簡單的服務來管理員工的基本信息。至于實例程序的結構,我們依然采用熟悉的包含三個項目(Service.Interface、Service和Client)的解決方案。如下所示的是定義在Service.Interface中用于表示員工的Employee類的定義,它是一個數據契約。
1: [DataContract(Namespace="http://www.artech.com/")]
2: public class Employee
3: {
4: [DataMember]
5: public string Id { get; set; }
6:
7: [DataMember]
8: public string Name { get; set; }
9:
10: [DataMember]
11: public string Department { get; set; }
12:
13: [DataMember]
14: public string Grade { get; set; }
15:
16: public override string ToString()
17: {
18: return string.Format("ID: {0,-5}姓名: {1, -5}級別: {2, -4} 部門: {3}",Id, Name, Grade, Department);
19: }
20: }
接下來我們定義了如下一個表示服務契約的接口IEmployeesService。和基于SOAP的服務契約定義不同,我們無需在相應的操作方法上面應用OperationContractAttribute特性,但是應用在接口/類上的ServiceContractAttribute特性仍是必需的。在這里替換OperationContractAttribute特性的分別是WebGetAttribute和WebInvokeAttribute,它們均定義在System.ServiceModel.Web程序集中。
1: [ServiceContract(Namespace="http://www.artech.com/")]
2: public interface IEmployees
3: {
4: [WebGet(UriTemplate = "all")]
5: IEnumerable
6:
7: [WebGet(UriTemplate = "{id}")]
8: Employee Get(string id);
9:
10: [WebInvoke(UriTemplate = "/", Method = "POST")]
11: void Create(Employee employee);
12:
13: [WebInvoke(UriTemplate = "/", Method = "PUT")]
14: void Update(Employee employee);
15:
16: [WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
17: void Delete(string id);
18: }
契約接口IEmployeesService中定義了5個操作,分別用于實現針對員工數據的獲取、添加、修改和刪除。按照REST設計原則,我們將被操作的員工信息體現為某種網絡資源,而操作類型最好與相應的HTTP方法相匹配。在操作方法中針對資源的操作類型與HTTP方法之間的匹配是通過應用在它們上面的WebGetAttribute和WebInvokeAttribute特性來體現。
WebGetAttribute針對GET方法,而其他的HTTP方法則通過WebInvokeAttribute的Method屬性來體現。在IEmployeesService中,兩個用于獲取員工信息GetAll和Get方法均應用了WebGetAttribute特性,而其他的Create、Update和Delete方法在應用了WebInvokeAttribute特性,并且其Method屬性被分別設置為PUT、POST和DELETE。
WebGetAttribute和WebInvokeAttribute和均具有相同的屬性UriTemplate,該屬性用于定義作為最終操作URI的模板。我們不僅可以通過UriTemplate屬性為操作指定一個相對于終結點地址的靜態路徑,還可以通過占位符實現路徑中的動態部分與參數之間的映射。
同樣以定義在契約接口IEmployeesService中的5個操作方法為例,如果終結點地址為http://127.0.0.1:3721/employees,由于用于返回所有員工列表的GetAll操作的UriTemplate被設置“All”,所以其地址為http://127.0.0.1:3721/employees。用于返回指定員工ID的Get操作的UriTemplate被設置成“{id}”,意味著我們直接在表示請求地址的URI中指定員工的ID,而它會自動映射為該操作方法的參數id。用于刪除某個指定員工的Delete操作具有相同的UriTemplate設置,而用于創建添加新員工和修改現有員工信息的Create和Update操作,由于作為參數的Employee對象具有ID屬性,所以直接采用終結點地址。
二、創建/寄宿服務
在控制臺程序Service中我們定義了如下一個實現了契約接口IEmployeesService的服務類型EmployeesService。簡單 起見,我們直接通過一個靜態字段employees表示存儲的員工列表,該靜態字段在初始化的工作中被添加了兩個ID分別為001和002的Employee對象。針對員工信息的獲取、添加、修改和刪除的操作均在此列表中進行。
1: public class EmployeesService : IEmployees
2: {
3: private static IList
4: {
5: new Employee{ Id = "001", Name="張三", Department="開發部", Grade = "G7"},
6: new Employee{ Id = "002", Name="李四", Department="人事部", Grade = "G6"}
7: };
8: public Employee Get(string id)
9: {
10: Employee employee = employees.FirstOrDefault(e => e.Id == id);
11: if (null == employee)
12: {
13: WebOperationContext.Current.OutgoingResponse.StatusCode =