初尝Web API《转》

HTTP 并不是只能用在网页中。它其实还是一个强大的平台,可以用来生成一些API,暴露服务和数据。HTTP很简单灵活,还非常普及。几乎所有你能想到的平台都有HTTP库,所以HTTP服务可以囊括很大范围的客户端,包括浏览器,移动设备和传统的桌面程序。

ASP.NET Web API 是.NET Framework上的一个框架,用来生成 web API。 本文将使用ASP.NET Web API来创建一个web API,返回一组商品。前端页面用jQuery来显示结果。

点此下载完整工程。

首先需要安装了ASP.NET MVC 4的 Visual Studio 。下面的用哪个都行:

  • Visual Studio 2012
  • Visual Studio Express 2012 for Web
  • Visual Studio 2010 且已安装 ASP.NET MVC 4 。
  • Visual Web Developer 2010 Express 且已安装 ASP.NET MVC 4 。

如果用的是 Visual Studio 2010 或者 Visual Web Developer 2010 Express ,需要另外安装 ASP.NET MVC 4 。本文的截图都是用的 Visual Studio Express 2012 for Web。

创建 Web API 工程

启动 Visual Studio ,在开始页里选择“新建项目”。或者从“文件”菜单里,选择“新建项目”。

在模板面板中,选择“已安装”,并展开 Visual C# 节点。在 Visual C# 下面,选择 Web。在项目模板列表中,选择 ASP.NET MVC 4 Web 应用程序。将项目命名为 "HelloWebAPI" 然后点击“确定”。

在弹出的“新 ASP.NET MVC 4 项目”对话框中,选择“Web API”然后点“确定”。

添加模型

模型是指程序里的对象。 ASP.NET Web API 能够自动序列化模型为JSON,XML或者其它的格式,然后将序列化后的数据写入HTTP响应信息体里。只要客户端能读到序列化格式,它就能反序列化为对象。大部分的客户端都能够解析XML或JSON。 而且,客户端通过设置HTTP请求信息里的Accept头就能够表明它想要什么样的格式。

我们就创建一个表示商品的模型来开始吧。

如果解决方案资源管理器没显示的话,点击“视图”菜单并选择“解决方案资源管理器”。在解决方案资源管理器重,右击“Models”文件夹。在弹出菜单中,选择“添加“,”类“。

将类命名为 "Product"。接下来在 Product 类里加入下面的属性:

namespace HelloWebAPI.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }
}

添加控制器

控制器是一个处理HTTP请求的对象。当你创建完项目以后,”新建项目“向导就自动创建了2个控制器。在解决方案资源管理器里展开”Controllers“目录就能看到了。

  • HomeController 是一个传统的 ASP.NET MVC 控制器。它只是负责处理站点的HTML页,跟Web API没有直接关系。
  • ValuesController 是一个示例 WebAPI 控制器。

注意  如果你之前已经搞过 ASP.NET MVC,那你肯定已经对控制器很熟了。它在Web API里也是类似的,只不过在Web API里控制器不是从Controller类继承而是从ApiController类继承了。你会注意到,第一个主要的不同点是Web API上的操作并不返回视图,而是返回数据。

解决方案资源管理里右击 ValuesController, 选择”删除“直接把他删掉。

如下所示,添加一个新的控制器:

解决方案资源管理里,右击 Controllers 目录,选择”添加“,”控制器“:

在”添加控制器“向导中,将控制器命名为 "ProductsController"。”模板“下拉框中,选择”空API控制器“。然后点”添加“。

”添加控制器“向导在Controllers目录下创建一个名为 ProductsController.cs 的控制器。

没有必要非得把控制器放到Controllers目录里。目录名并不重要,只是为了方便我们组织代码文件,这么起名比较简单。

如果这个文件没有打开,那就双击它打开(译注:老外真是啰嗦,像唐僧似的……)。添加如下的实现代码:

namespace HelloWebAPI.Controllers
{
    using HelloWebAPI.Models;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http;

    public class ProductsController : ApiController
    {

        Product[] products = new Product[]
        {
            new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
            new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
            new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
        };

        public IEnumerable<Product> GetAllProducts()
        {
            return products;
        }

        public Product GetProductById(int id)
        {
            var product = products.FirstOrDefault((p) => p.Id == id);
            if (product == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            return product;
        }

        public IEnumerable<Product> GetProductsByCategory(string category)
        {
            return products.Where(
                (p) => string.Equals(p.Category, category,
                    StringComparison.OrdinalIgnoreCase));
        }
    }
}

为了让例子保持简单,我们直接把产品存到控制器类里的一个固定数组里。当然,在实际的程序里需要从数据库里查询或者用其它的一些外部数据源。

控制器定义了三个方法,要么返回单个商品,要么返回一组产品:

  • GetAllProducts 方法返回所有的产品,返回类型为 IEnumerable<Product> 。
  • GetProductById 方法通过ID查询某个产品。
  • GetProductsByCategory 方法返回指定分类的所有产品。

完事儿了!web API已经能用了。每一个控制器上的方法都对应了一个URI:

控制器方法 URI
GetAllProducts /api/products
GetProductById /api/products/id
GetProductsByCategory /api/products/?category=category

客户端只要通过放松一个HTTP GET请求到URI就可以调用相应的方法。待会儿我们来看看这个映射是怎么做的。但首先我们先把它跑起来试试。

从浏览器调用 Web API

任何HTTP客户端都可以用来调用 web API。其实可以从web浏览器直接调用。

在 Visual Studio 里,选择“调试”菜单,然后“启动调试”,或者按F5键。 ASP.NET Development Server 就会启动起来(译者注:在VS2012默认的应该是IIS Express), 在屏幕的右下角会出现一个通知图标,显示它正运行在哪个端口。默认情况下, Development Server 会选择一个随机的端口号。

然后Visual Studio 会自动打开浏览器窗口, URL 指向 http//localhost:xxxx/, xxxx 就是端口号。首页应该看起来如下图:

首页是一个 ASP.NET MVC 视图,由 HomeController 类返回。想要调用 web API,就得用到前边儿列出来的URI之一。比如,要获取所有商品列表,那就浏览 http://localhost:xxxx/api/products/. (将 "xxxx" 替换为真实的端口号)

实际显示结果要看你使用什么浏览器来决定。IE会提示你打开或保存一个名为products的“文件”。

这个“文件”其实只是HTTP响应体。点击“打开”。在“打开方式”对话框“,选择”记事本“。点击”确定“,弹出提示的时候点”打开“。文件应该包含了一个JSON,表示产品的数组。

[{"Id":1,"Name":"Tomato soup","Category":"Groceries","Price":1.0},{"Id":2,"Name":
"Yo-yo","Category":"Toys","Price":3.75},{"Id":3,"Name":"Hammer","Category":
"Hardware","Price":16.99}]

如果是Mozilla Firefox,会在浏览器里以XML形式显示列表。

为什么会不一样呢?因为 Internet Explorer 和 Firefox 发送了不同的 Accept 头,所以 web API 在响应里就发送了不同的内容类型。

自己浏览这俩 URI 试试:

  • http://localhost:xxxx/api/products/1
  • http://localhost:xxxx/api/products?category=hardware

第一个应该返回ID等于1的条目。第二个应该返回Category等于”hardware“的所有产品列表(这里只有一个条目)。

用JavaScript和jQuery调用 Web API

前一节里我们直接在浏览器里访问 web API 。但是大部分 web API 主要目的还是有客户端程序以编程方式来用。所以我们来写一个简单的JavaScript客户端。

在解决方案资源管理器重,展开Views目录,然后展开它下面的Home目录。可以看到一个名为Index.cshtml的文件。双击这个文件打开。

Index.cshtml 使用 Razor 视图引擎 渲染HTML页。 但是此处我们不使用任何Razor特性,因为我要演示客户端如何使用纯HTML和Javascript访问服务。因此,删掉这个文件里的所有东西,用下面的代码替换之:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>ASP.NET Web API</title>
    <link href="../../Content/Site.css" rel="stylesheet" />
    <script src="../../Scripts/jquery-1.7.1.min.js" type="text/javascript">
        // TODO Add script
    </script>
</head>
<body id="body" >
    <div class="main-content">
        <div>
            <h1>All Products</h1>
            <ul id="products"/>
        </div>
        <div>
            <label for="prodId">ID:</label>
            <input type="text" id="prodId" size="5"/>
            <input type="button" value="Search" onclick="find();" />
            <p id="product" />
        </div>
    </div>
</body>
</html>

获取产品列表

要获取产品列表,通过发送 HTTP GET 请求到 "/api/products"。可以像下面这样用jQuery来实现:

<script type="text/javascript">
    $(document).ready(function () {
        // Send an AJAX request
        $.getJSON("api/products/",
        function (data) {
            // On success, ‘data‘ contains a list of products.
            $.each(data, function (key, val) {

                // Format the text to display.
                var str = val.Name + ‘: $‘ + val.Price;

                // Add a list item for the product.
                $(‘<li/>‘, { text: str })    
                .appendTo($(‘#products‘));  
            });
        });
    });
</script>

getJSON 函数用来发送 AJAX 请求。 响应将是一个JSON对象数组。getJSON的第二个参数是一个回调函数,当请求成功完成时将调用。

通过ID获取产品

要根据ID获取产品,通过发送 HTTP GET  请求到 "/api/products/id",这里的id就是产品的ID。将以下代码添加到脚本块儿里:

function find() {
    var id = $(‘#prodId‘).val();
    $.getJSON("api/products/" + id,
        function (data) {
            var str = data.Name + ‘: $‘ + data.Price;
            $(‘#product‘).text(str);
        })
    .fail(
        function (jqXHR, textStatus, err) {
            $(‘#product‘).text(‘Error: ‘ + err);
        });
}            

我们再一次通过调用 jQuery 的 getJSON 函数来发送 AJAX 请求,但这次我们用ID来构造这个请求URI。这个请求的响应是一个JSON,表示单个产品对象。

完整的 Index.cshtml 文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>ASP.NET Web API</title>
    <link href="../../Content/Site.css" rel="stylesheet" />
    <script src="../../Scripts/jquery-1.7.1.min.js"
        type="text/javascript"></script>

        <script type="text/javascript">
            $(document).ready(function () {
                // Send an AJAX request
                $.getJSON("api/products/",
                function (data) {
                    // On success, ‘data‘ contains a list of products.
                    $.each(data, function (key, val) {

                        // Format the text to display.
                        var str = val.Name + ‘: $‘ + val.Price;

                        // Add a list item for the product.
                        $(‘<li/>‘, { text: str })
                        .appendTo($(‘#products‘));
                    });
                });
            });

            function find() {
                var id = $(‘#prodId‘).val();
                $.getJSON("api/products/" + id,
                    function (data) {
                        var str = data.Name + ‘: $‘ + data.Price;
                        $(‘#product‘).text(str);
                    })
                .fail(
                    function (jqXHR, textStatus, err) {
                        $(‘#product‘).text(‘Error: ‘ + err);
                    });
            }
        </script>

</head>
<body id="body" >
    <div class="main-content">
        <div>
            <h1>All Products</h1>
            <ul id="products"/>
        </div>
        <div>
            <label for="prodId">ID:</label>
            <input type="text" id="prodId" size="5"/>
            <input type="button" value="Search" onclick="find();" />
            <p id="product" />
        </div>
    </div>
</body>
</html>

运行程序

按下 F5 启动调试程序。网页应该如下图所示:

这不是最好的web设计,但它演示了HTTP服务是可行的。通过在文本框内输入ID就可以通过这个ID获取产品。

如果输入了无效ID,服务器将返回一个HTTP错误:

理解路由

本节解释ASP.NET Web API是如何将URI映射到控制器方法的。详见 Routing in ASP.NET Web API.

对于每一个HTTP消息, ASP.NET Web API 框架通过询问路由表来决定由哪个控制器接收。当新建一个Web API项目时,项目就包含了一个默认的路由,如下所示:

/api/{controller}/{id}

{controller} 和 {id} 是占位符。当框架看到匹配此模式的URI时,它会去找相应的方法来调用,匹配规则如下:

  • {controller} 与控制器名称匹配。
  • HTTP 请求方法与方法名匹配。 (此规则只对 GET, POST, PUT, 和 DELETE 请求使用.)
  • {id}, 如果有,与名为id的方法参数匹配。
  • 可能的话,查询参数与参数名称匹配。

基于我们当前的实现,这里是一些示例请求,以及各自的操作。

URI HTTP 方法 操作
/api/products GET GetAllProducts()
/api/products/1 GET GetProductById(1)
/api/products?category=hardware GET GetProductsByCategory("hardware")

在第一个例子中, "products" 与名为 ProductsController 的控制器匹配。由于是一个 GET 请求,所以框架在ProductsController 上去找名字以"Get..."开头的方法。此外,URI不包含可选的 {id} 段,所以框架去找没有参数的方法。ProductsController::GetAllProducts 方法满足所有这些要求。

第二个例子是一样的,除了URI包含了 {id} 部分。因此,框架调用 GetProduct,它有一个名为id的参数。还有,注意URI中值“5”作为id参数传入。框架会基于方法签名,自动将“5"转换为int类型。

这里是一些会导致路由错误的请求:

URI HTTP 方法 操作
/api/products/ POST 405 Method Not Allowed
/api/users/ GET 404 Not Found
/api/products/abc GET 400 Bad Request

第一个例子,客户端发送了一个 HTTP POST 请求。框架去找名字以”Post...“开头的方法。但是在ProductsController里根本不存在这样的方法,所以框架返回一个 HTTP 响应,状态405,Method Not Allowed。

对于 /api/users 的请求失败,因为压根就没有名为 UsersController 的控制器。对 api/products/abc 的请求失败,因为id参数是int类型,而 URI 段的"abc" 无法转换为int。

使用 F12 查看 HTTP 请求和响应

当使用 HTTP 服务时,查看HTTP请求和请求消息非常有用。在IE9里通过F12开发者工具就能做到。IE9里,按下F12,打开工具。点击”网络“页签,按下”开始捕获“按钮。回到网页并按F5重新加载网页。IE就会捕获浏览器和服务器间的HTTP流量。”摘要视图“显示一个页面的所有网络流量。

找到相对URI “api/products/” 的条目。选择此条目点击”转到详细视图“。在详细视图里,可以看到请求和响应的标头和正文。比如,如果点击”请求标头“页签,就可以看到客户端在Accept标头里请求了"application/json"。

如果点击”响应正文“标签,可以看到产品列表时如何序列化为JSON的。其它的浏览器也有类似的功能。另一个有用的工具是 Fiddler,一个web 调试代理。你可以用Fiddler来查看HTTP流量,还可以组合HTTP请求,这样你可以对请求中的HTTP标头进行完全控制。

下一步

想查看完整的支持POST, PUT, 和DELETE操作的HTTP服务例子,见:

Web API 不要求一定用 ASP.NET MVC. 其它的选择见:

原文地址:http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api

时间: 2024-10-09 15:45:30

初尝Web API《转》的相关文章

Web Api入门

http://blog.csdn.net/ojlovecd/article/details/8169822 初尝Web API 分类: ASP.NET MVC教程 2012-11-10 22:05 18557人阅读 评论(2) 收藏 举报 apiasp.netASP.NETAsp.NetmvcMVCwebWeb 目录(?)[+] ASP.NET Web API 是.NET Framework上的一个框架,用来生成 web API. 本文将使用ASP.NET Web API来创建一个web API

Web API初印象

理解REST,RESTful和Web API 1.REST:Representational State Transfer表征状态转移,是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格.REST设计风格有如下几点: ①资源由URI来指定 ②对资源的操作(即通常所说的CURD)包括获取.创建.修改和删除资源,这些操作正好对应HTTP协议提供的GET.POST.PUT和DELETE方法 ③输出格式通常是XML或JSON 2.RESTful:是一种使用HTTP协议并遵循

学习ASP.NET Web API框架揭秘之“HTTP方法重写”

最近在看老A的<ASP.NET Web API 框架揭秘>,这本书对于本人现阶段来说还是比较合适的(对于调用已经较为熟悉,用其开发过项目,但未深入理解过很多内容为何可以这样“调用”).看到第四章了,有些内容看着虽能理解,但未遇到过具体的问题,看起来也就没有豁然开朗之感.同时,有些内容是一眼就觉得“这是干货”,可能是之前遇到过某些问题,当时用一些搓办法解决,但现在看到书中的示例就如获至宝.所以,就挑些单独能拎出来且马上就能在项目中应用的内容出来与大家分享交流下吧.其中会穿插一些框架中的知识点.不

(转)集成架构:对比 Web API 与面向服务的架构和企业应用程序集成

摘要:总体上讲,SOA 和 Web API 似乎解决的是同一个问题:以实时的.可重用的方式公开业务功能.本教程将分析这些举措有何不同,以及如何将它们融入到一个不断演变的集成架构中.文中还将讨论 API 管理与在它之前出现的集成架构(比如 SOA 和 EAI)有何不同. 简介 几乎所有企业都有多个应用程序作为其关键数据的记录系统,而且还拥有它们赖以创业的业务功能.因此,一些组织想要不断向其企业内外更广泛的受众揭示这些操作系统中的宝贵资产,我们对此已司空见惯.但是,这需要时间.在本教程中,我们将介绍

Dynamics CRM 2015/2016 Web API:基于视图的数据查询

Dynamics CRM 2016 Web API支持基于视图来查询数据,博主初看到该Feature,着实让我眼前一亮,这个功能太给力了,完全颠覆了之前复杂繁琐的取数方式了,现在的视图真正到了定义一次,处处复用的地步了!使用方法也很简单,只需要加个参数并指定需要调用的View ID就好了.接下来我给大家演示3个比较常用的场景:调用公共视图,调用私有视图,调用SubGrid视图. 公共视图 什么是公共视图?就是大家都有权限访问的视图,比如客户实体上的我的可用客户视图,我们一般在UI上面这么调用它们

Gitlab CI 自动部署 asp.net core web api 到Docker容器

为什么要写这个? 在一个系统长大的过程中会经历不断重构升级来满足商业的需求,而一个严谨的商业系统需要高效.稳定.可扩展,有时候还不得不考虑成本的问题.我希望能找到比较完整的开源解决方案来解决持续集成.监控报警.以及扩容和高可用性的问题.是学习和探索的过程分享给大家,也欢迎同行的人交流. 先来一个三步曲,我们将完成通过GitLab CI 自动部署 net core web api 到Docker 容器的一个示例.这是第一步,通过此文您将了解如何将net core web api 运行在Docker

集成架构:对比 Web API 与面向服务的架构和企业应用程序集成(转)

http://kb.cnblogs.com/page/521644/ 摘要:总体上讲,SOA 和 Web API 似乎解决的是同一个问题:以实时的.可重用的方式公开业务功能.本教程将分析这些举措有何不同,以及如何将它们融入到一个不断演变的集成架构中.文中还将讨论 API 管理与在它之前出现的集成架构(比如 SOA 和 EAI)有何不同. 简介 几乎所有企业都有多个应用程序作为其关键数据的记录系统,而且还拥有它们赖以创业的业务功能.因此,一些组织想要不断向其企业内外更广泛的受众揭示这些操作系统中的

Asp.Net MVC及Web API框架配置会碰到的几个问题及解决方案 (精髓)

前言 刚开始创建MVC与Web API的混合项目时,碰到好多问题,今天拿出来跟大家一起分享下.有朋友私信我问项目的分层及文件夹结构在我的第一篇博客中没说清楚,那么接下来我就准备从这些文件怎么分文件夹说起.问题大概有以下几点: 1.项目层的文件夹结构 2.解决MVC的Controller和Web API的Controller类名不能相同的问题 3.给MVC不同命名空间的Area的注册不同的路由 4.让Web API路由配置也支持命名空间参数 5.MVC及Web API添加身份验证及错误处理的过滤器

C#开发微信门户及应用(47) - 整合Web API、微信后台管理及前端微信小程序的应用方案

在微信开发中,我一直强调需要建立一个比较统一的Web API接口体系,以便实现数据的集中化,这样我们在常规的Web业务系统,Winform业务系统.微信应用.微信小程序.APP等方面,都可以直接调用基于JSON数据格式的Web API接口,在我之前的几篇随笔中,对这方面都有一定的介绍,本篇继续这个主题,细致深入的阐述如何在接口和源码的基础上整合Web API.微信后台管理及前端微信小程序的应用方案. 1.基于Web API的微信开发框架 首先我们各个业务模块,都应该围绕着Web API进行展开,