微软在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 =