Web API 是ASP.NET平台新加的一个特性,它可以简单快速地创建Web服务为HTTP客户端提供API。Web API 使用的基础库是和一般的MVC框架一样的,但Web API并不是MVC框架的一部分,微软把Web API相关的类从 System.Web.Mvc 命名空间下提取了出来放在 System.Web.Http 命名空间下。这种理念是把 Web API 作为ASP.NET 平台的核心之一,以使Web API能使用在其他的Web应用中,或作为一个独立的服务引擎。本文将先带大家理解Web API,再教大家在MVC中使用Web API。

本文目录

为了更好的理解Web API,先带大家了解一下 REST 和 维基百科。

REST(全名:Representational State Transfer),中文翻译是表征状态转移(也有叫表述性状态转移),Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。

REST 从资源的角度来观察整个网络,分布在各处的资源由URI确定,而客户端的应用通过URI来获取资源的表征。获得这些表征致使这些应用程序转变了其状态。随着不断获取资源的表征,客户端应用不断地在转变着其状态,所谓表征状态转移(Representational State Transfer)。

目前REST),其中REST模式的Web服务与复杂的SOARPC对比来讲显的更加简洁,越来越多的web服务开始采用REST风格设计和实现。

需要注意的是,REST是设计风格而不是标准,但REST设计风格常基于使用HTTPURI,和XML以及HTML这些现有的广泛流行的协议和标准。REST设计风格有如下要点:

  • 资源是由URI来指定。
  • 对资源的操作包括获取、创建、修改和删除资源,这些操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法。
  • 通过操作资源的表现形式来操作资源。
  • 资源的表现形式则是XML或HTML,取决于读者是机器还是人,是消费web服务的客户软件还是web浏览器。当然也可以是任何其他的格式,如JSON。

另外,使用REST需要满足一些要求,如客户端和服务器结构、连接协议具有无状态性、能够利用Cache机制增进性能等。

RESTful Web API(也称为RESTful Web服务)是一个使用HTTP并遵循REST原则的Web服务。它从以下请求资源的三个方面进行定义:

  • URI,比如:http://example.com/resources/。
  • Web服务接受与返回的互联网媒体类型,比如:JSON,XML ,YAML 等。
  • Web服务在该资源上所支持的一系列请求方法(比如:POST,GET,PUT或DELETE)。

本文要讲的ASP.NET Web API 就是RESTful Web API的一种。下表列出了在实现 RESTful Web API 时HTTP请求方法的典型用途:

[ASP.NET MVC 小牛之路]18 - Web API

不像基于SOAP的Web服务,RESTful Web服务并没有“正式”的标准。这是因为REST是一种架构,而SOAP只是一个协议。虽然REST不是一个标准,但在实现RESTful Web服务时可以使用其他各种标准(比如HTTP,URL,XML,PNG等)。

那么REST和本文要讲的ASP.NET API又有什么关系呢?请继续往下阅读。

理解 ASP.NET Web API

ASP.NET Web API(本文简称Web API),是基于ASP.NET平台构建RESTful应用程序的框架。可以说 Web API 就是为在.NET平台下构建RESTful应用程序而生的,这也是本文要先介绍REST的原因。

Web API基于在 MVC 应用程序中添加的一个特殊的 Controller,这种 Controller 称为 API Controller,和MVC普通的 Controller 相比它主要有如下两个不同的特点:

  1. Action 方法返回的是 Model 对象,而不是ActionResult。
  2. 在请求时,Action 方法是基于 HTTP 请求方式来选择的。

第一个不同点很好理解,第二个不同点可能读者不太理解,一会看完本文的示例就理解了。

从API Controller的Action方法返回给客户端的Model对象是经过JSON编码的。API Controller的设计仅是为了提供传递Web数据的服务,因此它不支持View、Layout 和其它HTML呈现相关的特性。Web API 能支持任何有Web 功能的客户端,但最常用的是为Web应用程序中的Ajax请求提供服务。

正如在 ASP.NET MVC 小牛之路]14 - Unobtrusive Ajax 中演示的,我们也可以通过普通的Controller中创建Action方法来返回JSON格式的数据来支持Ajax,但 API controller 的方式可以使得数据相关的Action和View相关的Action分开,并且使得创建只为数据服务的应用更快更简单。

一般我们会在下面这两种情况下选择使用API Controler:

  1. 需要大量的返回JSON格式数据的Action方法。
  2. 和HTML无关,只是纯粹为数据提供服务。

如果你对上面这些概念还不太理解,没关系,当你阅读完本文后再回头看一下,你会对这些概念理解得更深些。

下面我会通过例子来解释Web API是如何工作的,它非常简单,因为很多东西都和我们之前讲过的MVC的东西相同。

创建 Web API 应用程序

作为本文的示例,我们创建一个名为 WebServices 的MVC应用程序,选择Web API模板。在本文的这个例子中,我们创建一个名为 Reservation 的Model,代码如下:

namespace WebServices.Models {
    public class Reservation {
        public int ReservationId { get; set; }
        public string ClientName { get; set; }
        public string Location { get; set; }
    }
}

为这个Model创建一个Repository 接口和它的一个简单的实现。如果你对 Repository 这个词不太理解,可以阅读:[ASP.NET MVC 小牛之路]05 - 使用 Ninject 。为了简单,我们直接在Models文件夹中添加一个名为 IReservationRepository 的接口,代码如下:

namespace WebServices.Models {
    public interface IReservationRepository {
        IEnumerable<Reservation> GetAll();
        Reservation Get(int id);
        Reservation Add(Reservation item);
        void Remove(int id);
        bool Update(Reservation item);
    }
}

创建一个名为 ReservationRepository 的类,实现 IReservationRepository 接口,代码如下:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
 
namespace WebServices.Models { 
    public class ReservationRepository : IReservationRepository { 
        private List<Reservation> data = new List<Reservation> { 
            new Reservation {ReservationId = 1,  ClientName = "Adam",  
                Location = "London"}, 
            new Reservation {ReservationId = 2,  ClientName = "Steve",  
                Location = "New York"},new Reservation {ReservationId = 3,  ClientName = "Jacqui",  
                Location = "Paris"}, 
        };

        private static ReservationRepository repo = new ReservationRepository();
        public static IReservationRepository getRepository() {
            return repo;
        }

        public IEnumerable<Reservation> GetAll() {
            return data;
        }

        public Reservation Get(int id) {
            var matches = data.Where(r => r.ReservationId == id);
            return matches.Count() > 0 ? matches.First() : null;
        }

        public Reservation Add(Reservation item) {
            item.ReservationId = data.Count + 1;
            data.Add(item);
            return item;
        }

        public void Remove(int id) {
            Reservation item = Get(id);
            if (item != null) {
                data.Remove(item);
            }
        }

        public bool Update(Reservation item) {
            Reservation storedItem = Get(item.ReservationId);
            if (storedItem != null) {
                storedItem.ClientName = item.ClientName;
                storedItem.Location = item.Location;
                return true;
            } else {
                return false;
            }
        }
    }
}
ReservationRepository

相关文章: