API(应用程序编程接口)是一种为软件应用程序提供服务的接口,它不需要与其消费者应用程序耦合。存在一个常见的误解,即认为开发Web API必须遵循ASP.NET MVC应用程序的模式。本文将介绍如何开发一个与ASP.NET MVC应用程序类型无关的独立API。
Web API是一个用于构建HTTP服务的框架。这些开发的服务可以被广泛的客户端使用,包括浏览器和移动设备。
Web API是ASP.NET MVC4的一个特性。它被包含在MVC 4中是因为它们的相似性。但这并不意味着总是需要创建ASP.NET MVC应用程序来开发Web API。可以在任何数量的应用程序中使用Web API。
就服务开发的理念而言,关键在于公开一些服务方法。不应该担心应用程序的类型。MVC应用程序是为了特定目的而设计的,有消费者端。应该独立于其消费者开发服务。在本例中,将通过控制台应用程序开发一个Web API。
在MVC之外开发Web API时,需要将Web API程序集引用到项目中。NuGet包管理器是向非ASP.NET项目添加Web API程序集的最简单方法。
从工具菜单中选择“程序包管理器”,然后选择“管理解决方案的NuGet包”。在“管理NuGet包”对话框中,选择“在线”。在搜索框中输入“Microsoft.AspNet.WebApi.SelfHost”。选择ASP.NET Web API Self Host包并点击安装。安装完成后,就可以在MVC之外开发Web API了。
启动Visual Studio并从开始页面选择“新建项目”。或者,从文件菜单中选择“新建”然后选择“项目”。在模板窗格中,选择“Visual C#”,然后选择“控制台应用程序”。输入项目名称并点击确定。
添加一个名为“Product.cs”的文件,以创建一个业务模型类。将通过Web API公开这个业务对象。
现在,需要添加Web API。从技术上讲,Web API方法只不过是一个Web API控制器类。为了添加控制器,右键单击项目并选择“添加新项”。在模板窗格中,选择“已安装模板”并展开“Visual C#”节点。在“Visual C#”下,选择“Web”。选择“Web API控制器类”。输入类的名称并点击确定。
一旦添加了控制器,将找到带有自动生成代码的类:
namespace WebAPISelfHost {
public class ProductController : ApiController {
// GET api/<controller>
public IEnumerable<string> Get() {
return new string[] {
"value1",
"value2"
};
}
// GET api/<controller>/5
public string Get(int id) {
return "value";
}
// POST api/<controller>
public void Post([FromBody]string value) {
}
// PUT api/<controller>/5
public void Put(int id, [FromBody]string value) {
}
// DELETE api/<controller>/5
public void Delete(int id) {
}
}
}
在上面的代码中,控制器类已经从ApiController类派生。这是Web API的关键类。如果想通过API公开一个控制器,必须从抽象类ApiController派生控制器。此外,还有四个自动生成的方法桩。这些是与四个REST动词GET、POST、PUT和DELETE相关的桩方法。由于Web API基于REST,框架为基于REST的Web服务提供了结构。
在示例中,将开发一个简单的服务来获取产品详细信息。因此,删除自动生成的代码并实现一个Web API GetProductList:
namespace WebAPISelfHost {
public class ProductsController : ApiController {
// [HttpGet]
public List<Product> GetProductList() {
List<Product> productLst = new List<Product>{
new Product{ProductID = "P01", ProductName = "Pen", Quantity = 10, Price = 12},
new Product{ProductID = "P02", ProductName = "Copy", Quantity = 12, Price = 20},
new Product{ProductID = "P03", ProductName = "Pencil", Quantity = 15, Price = 22},
new Product{ProductID = "P04", ProductName = "Eraser", Quantity = 20, Price = 27}
};
return productLst;
}
}
}
在API中,简单地返回一个产品列表。编译代码并构建项目。现在,Web API已经准备好了。需要托管开发的Web API。
可以在自己的主机进程中自托管Web API。在这里,将在控制台应用程序本身中自托管开发的Web API。在项目中引用System.Web.Http.SelfHost.dll。这个库为HTTP自托管服务提供了类。
打开Program.cs文件并添加以下命名空间:
using System.Web.Http;
using System.Web.Http.SelfHost;
现在,添加以下代码进行自托管:
static void Main(string[] args) {
var config = new HttpSelfHostConfiguration("http://localhost:8080");
config.Routes.MapHttpRoute(
"API Default",
"api/{controller}/{id}",
new { id = RouteParameter.Optional }
);
using (HttpSelfHostServer server = new HttpSelfHostServer(config)) {
server.OpenAsync().Wait();
Console.WriteLine("Press Enter to quit.");
Console.ReadLine();
}
}
在上面的代码中,创建了一个HttpSelfHostConfiguration的实例。类的重载构造函数期望一个Uri来监听特定的HTTP地址。在MapHttpRoute方法中,定义了API的路由模式。最后,使用配置在HttpSelfHostServer中。Web API是基于定义的配置托管的。
编译并运行项目。现在Web API已经启动并准备好服务了。注意:这个应用程序监听http://localhost:8080/。默认情况下,监听特定的HTTP地址需要管理员权限。因此,当运行应用程序时,可能会得到一个错误:“HTTP无法注册URL http://+:8080/”。为了避免这个错误,用提升的管理员权限运行Visual Studio。
现在是时候消费Web API了。让编写一个简单的控制台应用程序来调用Web API。将一个新的控制台应用程序项目添加到解决方案中。
由于API返回一个“产品”类型的列表,需要在客户端代码中添加stub产品类,以识别返回的类型。在客户端应用程序中添加Product.cs文件。
打开Program.cs文件。添加以下命名空间:
using System.Net;
using System.Net.Http;
using System.Runtime.Serialization.Json;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using EventStore.Serialization;
创建一个HttpClient类的实例,并将基地址设置为Web API的监听URI。
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:8080/");
添加接受头。在这里使用HTTP以及Web API的一个特性,称为“内容协商”。根据这个特性,客户端可以与服务器协商返回的数据格式。在这里,与服务器协商JSON格式。
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
使用HttpClient.GetAsync方法向Web API发送GET请求。提供路由模式。
// List all products.
HttpResponseMessage response = client.GetAsync("api/products").Result;
使用ReadAsAsync方法序列化响应。ReadAsAsync方法返回一个Task,它将产生一个指定类型的对象。GetAsync和ReadAsAsync方法都是异步的。它们返回代表异步操作的任务对象。获取Result属性会阻塞线程,直到操作完成。
if (response.IsSuccessStatusCode) {
// Parse the response body. Blocking!
var products = response.Content.ReadAsAsync().Result;
// Finally, print the data retrieved from the Web API:
foreach (var p in products) {
Console.WriteLine("{0}\t{1};\t{2}", p.ProductID, p.ProductName, p.Quantity);
Console.ReadLine();
}
} else {
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}