.NET Framework 4.0 中创建和使用 RESTful 服务






4.82/5 (78投票s)
介绍 REST 服务的基础知识,以及如何在 ASP.NET 中创建和使用 RESTful 服务。
关于本文
我写这篇文章是为了解释如何使用 .NET Framework 4.0 创建和使用 RESTful 服务。
什么是 Web 服务,WCF?
Web服务
Web 服务 就像是Web 服务器上的组件,客户端应用程序通过 Web 上的超文本传输协议 (HTTP) 请求来使用此服务。使用 ASP.NET,我们可以创建自定义的 Web 服务,并从任何客户端应用程序调用这些服务。
Web 服务是平台和编程语言无关的;它们使用简单对象访问协议 (SOAP) 消息来发送和接收数据。
WCF
Windows Communication Foundation (WCF) 是微软用于构建面向服务体系结构 (SOA) 的统一编程模型。使用它,开发人员可以构建跨平台的安全、可靠、事务性的解决方案。
WCF 支持集中式计算,即服务拥有独立的消费者。客户端可以消费多个服务,服务也可以被多个客户端消费。
要创建 WCF 中的基本应用程序,请参阅文章“Windows Communication Foundation 简介”。
Web 服务 | WCF 服务 |
Web 服务是为了构建应用程序而开发的,这些应用程序使用 HTTP 上的简单对象访问协议 (SOAP) 来发送和接收消息。消息的结构可以使用 XML Schema 来定义,并提供一个工具来方便地将消息序列化为 .NET Framework 对象或从 .NET Framework 对象反序列化。该技术可以自动生成元数据,以 Web 服务描述语言 (WSDL) 来描述 Web 服务。 | WCF 服务是为了构建应用程序而开发的,用于使用多种格式发送和接收消息,并通过任何传输协议进行传输。简单对象访问协议 (SOAP) 是默认使用的格式。消息的结构可以使用 XML Schema 来定义,并且有多种选项可将消息序列化为 .NET Framework 对象或从 .NET Framework 对象反序列化。WCF 可以自动生成元数据来描述使用该技术构建的应用程序的 WSDL,并且还提供了一个工具,用于从 WSDL 生成这些应用程序的客户端。 支持使用 HTTP、TCP 和其他网络协议发送消息。能够轻松切换消息协议。支持将服务托管在 Web 服务器以外的主机上。内置对最新 Web 服务标准 (SOAP 1.2 和 WS-*) 的支持,并能够轻松支持新标准。支持安全性、事务和可靠性。支持使用 SOAP 以外的格式发送消息。 |
XmlSerializer |
DataContractSerializer |
ASP.NET 依赖于 XmlSerializer 将 .NET Framework 类型表示的数据转换为 XML,以便发送到服务或从服务接收,并将其将接收到的 XML 数据转换为 .NET Framework 对象。定义 ASP.NET 服务要使用的复杂数据类型需要定义 .NET Framework 类,以便 XmlSerializer 可以对其进行 XML 序列化和反序列化。 |
DataContractAttribute 表示类型的零个或多个字段或属性要被序列化,而 DataMemberAttribute 表示特定的字段或属性要被序列化。DataContractAttribute 可以应用于类或结构。DataMemberAttribute 可以应用于字段或属性,并且应用了该属性的字段和属性可以是 public 或 private 。应用了 DataContractAttribute 的类型实例在 WCF 中被称为数据约定。它们使用 DataContractSerializer 序列化为 XML。 |
XmlSerializer 和 System.Xml.Serialization 命名空间中的属性旨在允许您将 .NET Framework 类型映射到 XML Schema 中定义的任何有效类型,因此它们提供了对类型如何在 XML 中表示的精确控制。 |
DataContractSerializer 、DataContractAttribute 和 DataMemberAttribute 对类型如何在 XML 中表示的控制非常少。您只能指定用于在 XML 中表示类型及其字段或属性的命名空间和名称,以及字段和属性在 XML 中出现的顺序。表示 .NET 类型所使用的 XML 结构的其余部分由 DataContractSerializer 决定。通过不允许对类型如何在 XML 中表示的过多控制,DataContractSerializer 的序列化过程变得高度可预测,从而更容易优化。 |
与 WCF DataContractSerializer 相比,性能较低。 |
DataContractSerializer 设计的实际好处是更好的性能,大约提高了百分之十。 |
用于 XmlSerializer 的属性不指示类型的哪些字段或属性被序列化为 XML。 |
用于 DataContractSerializer 的 DataMemberAttribute 明确显示了哪些字段或属性被序列化。因此,数据约定是关于应用程序要发送和接收的数据结构的显式约定。 |
XmlSerializer 只能将 .NET 对象的 public 成员转换为 XML。 |
DataContractSerializer 可以根据成员的访问修饰符将对象的成员转换为 XML。 |
集合类的实例只有在类实现了 IEnumerable 或 ICollection 接口时才能序列化为 XML。 |
DataContractSerializer 更有可能在不修改类型定义或开发包装器的情况下,将任何预先存在的 .NET 类型的实例序列化为 XML。 |
实现 IDictionary 接口的类,如 Hashtable ,不能序列化为 XML。 |
它可以将实现 IDictionary 接口的 Hashtable 等类型转换为 XML。 |
XmlSerializer 不支持版本控制。 |
DataContractSerializer 包含一些版本控制支持。 |
XmlSerializer 默认序列化类型在语义上与 XML 相同。 |
DataContractSerializer 序列化类型,前提是 XML 的命名空间已显式定义。 |
什么是 REST & RESTful?
Representational State Transfer (REST) 由Roy Fielding 于 2000 年提出;它是一种大规模网络软件的架构风格,利用了万维网的技术和协议。REST 说明了如何定义和寻址集中式数据对象或资源,强调信息的易于交换和可扩展性。
2000 年,HTTP 规范的主要作者之一 Roy Fielding 撰写了题为《架构风格与网络化软件体系结构的构建》的博士论文。
REST,一种用于构建分布式超媒体驱动应用程序的架构风格,通过定义实现统一接口的资源,使用标准的 HTTP 动词(GET
、POST
、PUT
和 DELETE
),并可通过统一资源标识符 (URI) 进行定位/标识,从而涉及构建面向资源架构 (ROA)。
REST 不与任何特定的技术或平台绑定——它仅仅是一种设计事物以使其像 Web 一样工作的模式。人们经常称遵循此理念的服务为“RESTful 服务”。使用 REST 架构风格开发的 WCF 服务被称为 RESTful 服务。
WCF 服务 | RESTful 服务 |
必须为每个网络协议创建终结点。 | 可以通过“Web”使用 HTTP 请求/响应消息进行连接。 |
它基于远程过程调用 (RPC) 工作。 | 它与 HTTP 的统一接口协同工作。 |
必须在客户端应用程序中添加服务引用。 | 无需在客户端应用程序中添加服务引用。 |
什么是 REST Starter Kit?
WCF REST Starter Kit 是一组 .NET Framework 类以及 Visual Studio 功能和模板,使用户能够创建和访问 REST 风格的 Windows Communication Foundation (WCF) 服务。这些服务基于 .NET 3.5 SP1 中提供的 WCF Web 编程模型。Starter Kit 还包含所有功能的完整源代码、详细的代码示例和单元测试。
创建基本的 RESTful 服务
步骤 1
使用 VS2010 创建新的 WCF 项目。
语言 | Visual C# 或 Visual Basic |
目标框架 | .NET Framework 4 |
已安装模板 | WCF |
模板 | WCF 服务应用程序 |
名称 | RESTFulDemo |
第二步
删除现有的 IService1.cs 和 Service1.svc 文件,并创建两个新文件:IRESTService.cs 和 RESTService.cs。
步骤 3
在 IService.cs 中创建 Person 实体(可以单独创建),并为此实体编写一个简单的成员。对于 DataContractSerialization
,用 DataContract
和 DataMember
属性装饰此类及其成员。请看下面的代码。
[DataContract]
public class Person
{
[DataMember]
public string ID;
[DataMember]
public string Name;
[DataMember]
public string Age;
}
Person
类及其成员,使用 System.Runtime.Serialization
命名空间用 [DataContract]
和 [DataMember]
装饰。
[DataContract]
– 一个可以在网络上传输的实体类。[Datamember]
– 只有用[Datamember]
装饰的属性才能被序列化,并且类的属性也必须用[DataContract]
装饰。
步骤 4
在 IRESTService
类和接口中创建方法,并用 [ServiceContract]
装饰,其成员用 [OperationContrat]
装饰,使用 System.ServiceModel
命名空间。
[ServiceContract]
public interface IRestSerivce
{
[OperationContract]
Person CreatePerson(Person createPerson);
[OperationContract]
List<person> GetAllPerson();
[OperationContract]
Person GetAPerson(string id);
[OperationContract]
Person UpdatePerson(string id, Person updatePerson);
[OperationContract]
void DeletePerson(string id);
}
[ServiceContract]
- 服务约定将类或接口公开给客户端应用程序,其中可能包含一个或多个[OperationContract]
方法。[OperationContract]
- 表明方法定义了一个应用程序服务约定中的操作,即只有用[OperationContract]
装饰的方法对 WCF 客户端应用程序可见,此方法的类也必须用[ServiceContract]
装饰。
步骤 5
到目前为止,代码与普通 WCF 服务相似。RESTful 服务在 HTTP 协议下工作,因此需要包含两个重要属性 WebGet
和 WebInvoke
(System.ServiceModel.Web
命名空间)才能使此应用程序成为 RESTful 服务。
WebGet 和 WebInvoke
WebGet 操作在逻辑上是从服务操作接收信息,并且可以通过 REST 编程模型进行调用。WebGet
属性除了 OperationContract
外还应用于服务操作,并将操作与 UriTemplate
以及 HTTP 协议的 Get 动词关联起来。
WebInvoke 操作在逻辑上提升了服务选项,并且可以通过 REST 编程模型进行调用。WebInvoke
属性除了 OperationContract
外还应用于服务操作,并将操作与 UriTemplate
以及表示调用的底层传输动词(例如,HTTP POST
、PUT
或 DELETE
)关联起来。WebInvoke
有一个名为 Method
的属性,它允许指定不同类型的 HTTP 方法(POST
、PUT
或 DELETE
),默认情况下 Method
是 POST
。
[ServiceContract]
public interface IRestSerivce
{
//POST operation
[OperationContract]
[WebInvoke(UriTemplate = "", Method = "POST")]
Person CreatePerson(Person createPerson);
//Get Operation
[OperationContract]
[WebGet(UriTemplate = "")]
List<person> GetAllPerson();
[OperationContract]
[WebGet(UriTemplate = "{id}")]
Person GetAPerson(string id);
//PUT Operation
[OperationContract]
[WebInvoke(UriTemplate = "{id}", Method = "PUT")]
Person UpdatePerson(string id, Person updatePerson);
//DELETE Operation
[OperationContract]
[WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
void DeletePerson(string id);
}
请参阅修改后的 IRESTService
接口代码,其中 WebGet
和 WebInvoke
属性已装饰了 IRESTService
接口中的可用方法。
Person CreatePerson(Person createPerson);
//It is basically insert operation, so WebInvoke HTTP POST is used
List<person> GetAllPerson();
Person GetAPerson(string id);
//These two methods retrieve the information, so WebGet (HTTP Get) is used
Person UpdatePerson(string id, Person updatePerson);
//This method updates the available information, so WebInvoke HTTP PUT is used
void DeletePerson(string id);
//This method deletes the available information,
//so WebInvoke HTTP DELETE is used
步骤 6
在 RESTService
类中实现 IRESTService
并完成业务需求。请参阅下面的示例代码。
public class RestSerivce : IRestSerivce
{
List<person> persons = new List<person>();
int personCount = 0;
public Person CreatePerson(Person createPerson)
{
createPerson.ID = (++personCount).ToString();
persons.Add(createPerson);
return createPerson;
}
public List<Person> GetAllPerson()
{
return persons.ToList();
}
public Person GetAPerson(string id)
{
return persons.FirstOrDefault(e => e.ID.Equals(id));
}
public Person UpdatePerson(string id, Person updatePerson)
{
Person p = persons.FirstOrDefault(e => e.ID.Equals(id));
p.Name = updatePerson.Name;
p.Age = updatePerson.Age;
return p;
}
public void DeletePerson(string id)
{
persons.RemoveAll(e => e.ID.Equals(id));
}
}
步骤 7
为了使此服务能够以 ASP.NET 兼容模式运行,需要用 AspNetCompatibilityRequirements
属性装饰 RESTService
类。
[AspNetCompatibilityRequirements
(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class RESTSerivce : IRestSerivce
{
//Code Implementation
//. . . . . .
// . . . . . .
}
在上面的 RESTService
类中,还额外装饰了 ServiceBehavior
属性,它指定了服务操作的内部行为。
步骤 8
要使用此 RESTful 服务应用程序,需要托管此服务。因此,我们需要对运行 RESTService
进行以下修改。
修改 Web.Config 文件
删除 <system.servicemodel>
标签内的所有代码,并插入以下代码。
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
</serviceHostingEnvironment>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true"
automaticFormatSelectionEnabled="true"></standardEndpoint>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
<serviceHostingEnvironment>
标签有助于在 ASP.NET 兼容模式下运行应用程序。<standardEndpoints>
标签有助于为 RESTful 应用程序提供 Web 帮助。
添加 Global.asax 文件
我们可以使用 Global.asax 文件和以下代码来托管 RESTful 服务。
RouteTable.Routes.Add(new ServiceRoute
("RestService", new WebServiceHostFactory(), typeof(RESTSerivce)));
步骤 9
运行 RESTFulDemo 应用程序,它将在浏览器中打开,地址栏将包含 RESTFulDemo 服务的基础地址。
https://:XXXX/
输入路由前缀名称“RestService”(在 global.asax 文件中给出的字符串值)。
https://:XXXX/RestService - 这是 Get
操作的基本 URI。
https://:XXXX/restservice/help - 它显示 RESTFulDemo 服务的帮助内容。
到目前为止,我们已经了解了如何创建和托管 RESTful 服务。接下来,我们将学习如何使用这个服务,因此我们将看到一个基本应用程序来使用这个RESTFulDemo 服务。
使用 RESTful 服务
步骤 1
向 RESTFulDemo
解决方案添加一个新的控制台应用程序。
语言 | Visual C# 或 Visual Basic |
目标框架 | .NET Framework 4 |
已安装模板 | WCF |
模板 | 控制台应用程序 |
名称 | RESTClient |
第二步
do
{
try
{
string content;
Console.WriteLine("Enter Method:");
string Method = Console.ReadLine();
Console.WriteLine("Enter URI:");
string uri = Console.ReadLine();
HttpWebRequest req = WebRequest.Create(uri) as HttpWebRequest;
req.KeepAlive = false;
req.Method = Method.ToUpper();
if (("POST,PUT").Split(',').Contains(Method.ToUpper()))
{
Console.WriteLine("Enter XML FilePath:");
string FilePath = Console.ReadLine();
content = (File.OpenText(@FilePath)).ReadToEnd();
byte[] buffer = Encoding.ASCII.GetBytes(content);
req.ContentLength = buffer.Length;
req.ContentType = "text/xml";
Stream PostData = req.GetRequestStream();
PostData.Write(buffer, 0, buffer.Length);
PostData.Close();
}
HttpWebResponse resp = req.GetResponse() as HttpWebResponse;
Encoding enc = System.Text.Encoding.GetEncoding(1252);
StreamReader loResponseStream =
new StreamReader(resp.GetResponseStream(), enc);
string Response = loResponseStream.ReadToEnd();
loResponseStream.Close();
resp.Close();
Console.WriteLine(Response);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
Console.WriteLine();
Console.WriteLine("Do you want to continue?");
} while (Console.ReadLine().ToUpper() == "Y");
步骤 3
在运行 RESTFulDemo
应用程序之前,设置多个启动项目。请参阅下图。
运行应用程序。它将同时运行 RESTFulDemo service
和 RESTClient
控制台应用程序。
HTTP GET 操作
输入方法 | Get |
输入 URI | https://:XXXX/restservice |
它会在控制台上显示 XML 输出。
HTTP POST 操作
输入方法 | Post |
输入 URI | https://:XXXX/restservice |
输入 XML 文件路径 | <输入输入 XML 文件路径> |
此操作会在服务中创建一个新的 Person 实体,可以在浏览器中使用 HTTP Get
操作进行查看。
在上面的屏幕中,调用 URI https://:XXXX/restservice/1,URI 以 Person ID (1) 结尾。它调用了服务操作。
[OperationContract]
[WebGet(UriTemplate = "{id}")]
Person GetAPerson(string id);
因此,它检索 ID 为 1 的 Person。
有关详细代码,请参阅附加的项目。
Fiddler 工具对测试 RESTful 服务非常有用。
结论
我希望本文能帮助您理解 RESTful 的基本概念,并使读者能够编写代码来创建和使用 RESTful 服务。请告诉我您的宝贵意见。
参考文献
- http://msdn.microsoft.com/en-us/library/aa738737.aspx
- http://msdn.microsoft.com/en-us/netframework/dd547388
- http://msdn.microsoft.com/en-us/library/dd203052.aspx
- http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webinvokeattribute.aspx
- http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webgetattribute.aspx