初试ASP.NET Web API/MVC API(附Demo)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初试ASP.NET Web API/MVC API(附Demo)相关的知识,希望对你有一定的参考价值。

参考页面:

http://www.yuanjiaocheng.net/webapi/media-formatter.html

http://www.yuanjiaocheng.net/webapi/webapi-filters.html

http://www.yuanjiaocheng.net/webapi/create-crud-api-1.html

http://www.yuanjiaocheng.net/webapi/create-crud-api-1-get.html

http://www.yuanjiaocheng.net/webapi/create-crud-api-1-post.html

写在前面

  ASP.NET Web API是??一个框架,可以很容易构建达成了广泛的HTTP服务客户端,包括浏览器和移动设备。是构建RESTful应用程序的理想平台的.NET框架。

  上面是微软对Web API给出的定义,其中包含两个关键字:HTTP和RESTful,其实从这一方面,大家就可以看出Web API和它的同胞兄弟:WebService和WCF有些不同了。

HTTP

技术分享

  对于HTTP大家都不是很陌生,因为我们每天浏览网页填写的URL就是HTTP开头,但只是知道有这个东西,确没有想过它是什么,就好像我们对世间万物有着模糊的认识,但认识东西的确很少。

  也可以从另一方面去理解,曾经看一个电视节目,有个嘉宾在录制的过程中,突然抬起头对着天花板仰望,然后主持人很惊讶问他在干吗?他说:我在思考宇宙有没有尽头?主持人接着问:那宇宙有没有尽头?他淡然的回答道:有就有,没有就没有。当然观众和主持人都笑作一团,你会笑吗?透过现象看本质,其实这个思想和老庄的思想很合拍,扯远了。

HTTP即超文本传送协议。

超文本传输协议 (HTTP-Hypertext transfer protocol) 是一种详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。

  从定义中看出HTTP是一种协议,超文本传输协议,那什么是超文本?和我们所说的富文本有些区别,超文本也是一种文本格式,那可以把它看成是文本与文本之间关联而组成的网状文本,有点类似于面向对象中对象的集合,虽然是对象的集合,但本身也是一个对象。

  HTTP协议有下面三个基本特点:

  • 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
  • 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
  • 无状态:无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。

  相对于Web API来说,HTTP不只是为了生成Web页面,它也是一个强大的平台建设公开服务和数据的API。HTTP是简单、 灵活和无处不在,因此几乎任何平台都可以有一个HTTP库,因此,HTTP服务可以到达范围广泛的客户端,包括浏览器、移动设备和传统的桌面应用程序。

RESTful

  RESTful架构概念是Fielding提出的,Fielding这号人物就是上面HTTP协议的主要设计者之一。我们先看下RESTful这个词,ful是跟在名词之后,表示程度,什么什么的,例如helpful乐于助人的,因此我们可以看出符合REST的架构就可以称为RESTful,接着我们看下REST,全称为“Representational State Transfer”,意为“表现层状态转化”

在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。  -Fielding

  这是Fielding在论文中所提到的,对于REST虽说是架构,但如果深入一点,就像是HTTP协议一样,可以看成一种规则或是协议。我们从一个地点到另一个地点,可以坐汽车、高铁、飞机等,对于REST就像是其中的一种交通方式,但REST的根本是HTTP协议,也就是说REST是基于HTTP协议的,这点就像坐汽车必须要有公路,坐高铁必须要有铁路是一样的道理,有时候为什么选用REST,就像我们从南京到徐州,选择坐高铁而不选择坐飞机一样。

  上面这个比喻可能不太恰当,但是思想都是相同的,如果有可能的话可以看下一些哲学方面的书,像庄子的道德经,毕竟编程是哲学或是艺术的另一类体现,又扯远了。

  “Representational State Transfer”我们分解下:

  • Representational 表现层:表现层表现什么,应该呈现资源(Resources),一个图片、一段文字、一个文件都成为资源,每个资源都用一个URI(统一资源定位符)指向它,表现层就是调用URI把资源呈现出来,而且只是呈现,不做其他操作。举个例子:有些网址最后的".html"后缀名是不必要的,因为这个后缀名表示格式,属于"表现层"范畴,而URI应该只代表"资源"的位置。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对"表现层"的描述。
  • State Transfer 状态转化:访问一个网站,就表示客户端和服务器发生一次交互行为,在这个过程中,就不发生数据和状态的转化,上面说到HTTP协议具有无状态性,如果客户端操作服务器,必须要状态转化,这个体现在表现层上,所以叫“表现层状态转化”

  通过上面的理解,可以总结下什么是RESTful架构:

  1. 每一个URI代表一种资源。
  2. 客户端和服务器之间,传递这种资源的某种表现层。
  3. 客户端通过四个HTTP动词(PUT、GET、POST和DELETE),对服务器端资源进行操作,实现"表现层状态转化"。

创建Web API

  关于Web API的实现方式,.net提供了一套机制就是ASP.NET MVC API,类似MVC的方式,实现起来很简单,也不需要你去关注HTTP和RESTful的一些东西,当你去新建项目的时候,一切东西.net都帮你搞定了,是好还是不好?只能呵呵笑过。

  下面我们就一步一步的创建一个ASP.NET MVC API

  1,新建ASP.NET MVC WebMvcApiDemo程序,选择Web API模板类型。

技术分享

技术分享

  2,创建News模型,虽然创建的是MVC项目,但是我们一般只用到控制器和模型。

 1     public class News
 2     {
 3         /// <summary>
 4         /// 新闻ID
 5         /// </summary>
 6         public int Id { get; set; }
 7         /// <summary>
 8         /// 新闻标题
 9         /// </summary>
10         public string Title { get; set; }
11         /// <summary>
12         /// 新闻内容
13         /// </summary>
14         public string Content { get; set; }
15         /// <summary>
16         /// 新闻作者
17         /// </summary>
18         public string Author { get; set; }
19         /// <summary>
20         /// 发布新闻时间
21         /// </summary>
22         public DateTime CreateTime { get; set; }
23     }

  3,创建数据模拟类NewsRepository,用于查询数据。

 1     public class NewsRepository
 2     {
 3         public IEnumerable<News> GetAllNews()
 4         {
 5             News[] news = new News[] 
 6             { 
 7                 new News { Id = 1, Title="新闻标题1", Content="新闻内容1", Author="xishuai", CreateTime=DateTime.Now }, 
 8                 new News { Id = 2, Title="新闻标题2", Content="新闻内容2", Author="xishuai", CreateTime=DateTime.Now }, 
 9                 new News { Id = 3, Title="新闻标题2", Content="新闻内容3", Author="xishuai", CreateTime=DateTime.Now }
10             };
11             return news;
12         }
13     }

  4,创建NewsController控制器,注意的是:新建控制器的时候,模板选择“空 API 控制器”,与MVC控制器不同的是,API控制器继承ApiController基类。在我们新建ApiDemo的MVC项目的时候,自动生成了一个ValuesController API控制器,打开后我们发现,有很多自动生成的方法,请求方式就是我们上面说GET、POST、PUT和DELETE的四种HTTP请求方式,我们这边做一个Get的,获取全部新闻或是指定新闻ID获取,返回结果格式为XML。

 1     public class NewsController : ApiController
 2     {
 3         /// <summary>
 4         /// GET获取全部新闻
 5         /// </summary>
 6         /// <returns></returns>
 7         [HttpGet]
 8         public HttpResponseMessage GetAllNews()
 9         {
10             var news = new NewsRepository().GetAllNews();
11             return new HttpResponseMessage()
12             {
13                 RequestMessage = Request,
14                 Content = new XmlContent(SimpleXmlConverter.ToXmlDocument<News>(news, "NewsRoot"))
15             };
16         }
17 
18         /// <summary>
19         /// GET获取指定ID新闻
20         /// </summary>
21         /// <param name="ID"></param>
22         /// <returns></returns>
23         [HttpGet]
24         public HttpResponseMessage GetNewsByID(int ID)
25         {
26             var news = new NewsRepository().GetAllNews().Where((p) => p.Id == ID);
27             return new HttpResponseMessage()
28             {
29                 RequestMessage = Request,
30                 Content = new XmlContent(SimpleXmlConverter.ToXmlDocument<News>(news, "NewsRoot"))
31             };
32         }
33     }

  这里面主要用到两个转化类:XmlContent和SimpleXmlConverter,有关这两个类的详细代码可以下载Demo看下。

  5,路由配置Web API和MVC的路由配置很相似,主要区别是Web API使用HTTP方法而不是URI路径来选择动作,路由文件WebApiConfig,如下:

1             config.Routes.MapHttpRoute(
2                 name: "DefaultApi",
3                 routeTemplate: "api/{controller}/{action}/{id}",
4                 defaults: new { id = RouteParameter.Optional }
5             );

  其实写到这里创建Web API的代码就差不多了,当然复杂的操作可以扩充,用.net开发就是这么简单,只要完成业务逻辑就行了,呵呵。

调用Web API

  调用Web API有很多种方式,js可以调用,就像我们写MVC请求数据一样,这种是同一域下调用,Web API也是这种方式就没什么意思了,如果使用js调用就必须跨域操作,这边我们使用HttpClient的方式。

  1,新建控制台应用程序-ClientDemo。

技术分享

  2,安装Web API 客户端库,工具-程序包管理器-程序包管理控制平台,输入命令:Install-Package Microsoft.AspNet.WebApi.Client

  上面新建的ClientDemo项目.net framework版本是4.0,安装HttpClient的时候报下面错误:

技术分享

  .net framework版本改为4.5就安装成功了,难道HttpClient只支持4.5以上?查了下MSDN,HttpClient确实只支持.net framework4.5,难道以前程序如果使用HttpClient要把.net framework改成4.5?有点郁闷。

技术分享

  4,创建HttpClient,先贴下代码:

 1         static void Main(string[] args)
 2         {
 3             RunAsync().Wait();
 4         }
 5 
 6         static async Task RunAsync()
 7         {
 8             using (var client = new HttpClient())
 9             {
10                 client.BaseAddress = new Uri("http://localhost:8077/");
11                 client.DefaultRequestHeaders.Accept.Clear();
12                 client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
13 
14                 string xmlString = await client.GetStringAsync("api/News/GetAllNews");
15                 XmlDocument xmlDoc = new XmlDocument();
16                 xmlDoc.LoadXml(xmlString);
17                 XmlNodeList nodeList = xmlDoc.GetElementsByTagName("News");
18                 foreach (XmlNode node in nodeList)
19                 {
20                     Console.WriteLine("新闻ID:" + node.SelectSingleNode("Id").InnerText);
21                     Console.WriteLine("新闻标题:" + node.SelectSingleNode("Title").InnerText);
22                     Console.WriteLine("新闻内容:" + node.SelectSingleNode("Content").InnerText);
23                     Console.WriteLine("作者:" + node.SelectSingleNode("Author").InnerText);
24                     Console.WriteLine("新闻发布时间:" + node.SelectSingleNode("CreateTime").InnerText);
25                     Console.WriteLine("======================");
26                 }
27                 Console.ReadKey();
28             }
29         }

  Main 函数调用一个名为RunAsync的异步方法,然后会阻止,直到RunAsync完成。许多的HttpClient方法是异步,因为他们执行网络 i/o 操作。MediaTypeWithQualityHeaderValue是定义传输格式,如果使用json则为“application/json”,这边要与Web API格式一致,XML获取使用的是GetStringAsync方法,然后转换为XmlDocument,网上找了一种GetStreamAsync方法获取,通过Stream转化为字符串,但是转化后的字符串为空。

  上面调用Web API的是获取全部新闻,如果调用通过新闻ID获取新闻,GetStringAsync的方法参数只需要改为“api/News/GetNewsByID/新闻ID”就可以了。

  5,关于Web API的发布问题,这个问题花了不少时间,一个一个问题出现及解决,首先我们先不急着调用,先发布浏览,如果浏览器浏览没问题的话再调用。Web API的发布和MVC差不多,需要注意下面几点:

  • 文件权限别忘了配置,要配置every one。
  • 应用程序池选择“ASP.NET v4.0 DefaultAppPool”。
  • 选择应用程序池之后要配置“ISAPI 和 CGI 限制”的4.0版本设置为允许,要不然出现“由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页面。”的错误。
  • “Newtonsoft.Json”文件引用。
  • “An error has occurred.Multiple actions were found that match the request”,这个错误信息是Web API的路由没有配置好,要检查下。
  • “Response status code does not indicate success: 404 (Not Found)”,这个错误信息也是路由问题。
  • “Response status code does not indicate success: 500 (Internal Server Error).”,这个是服务器问题,也就是Web API的代码问题。

运行截图及Demo下载

  Web API浏览器请求截图:

技术分享

  Web API发布运行截图:

技术分享

  客户端调用运行截图:

技术分享

  Demo下载地址:http://pan.baidu.com/s/1gdopRub

  HTTP请求的四种方法(PUT、GET、POST和DELETE)本篇只是讲到GET,HTTP的数据传输格式(json、xml等)也只是说了XML,但都是大同小异,举一反三可得。

  如果你觉得本篇文章对你有所帮助,请点击右下部“推荐”,^_^



以上是关于初试ASP.NET Web API/MVC API(附Demo)的主要内容,如果未能解决你的问题,请参考以下文章

Asp.Net Web API 2第五课——Web API路由

ASP.NET Web API教程1.1 第一个ASP.NET Web API

Asp.Net Web API 2第三课——.NET客户端调用Web API

Web API1.1 ASP.NET Web API入门

Asp.Net Web API 2第六课——Web API路由和动作选择

Asp.Net Web API 2第十三课——ASP.NET Web API中的JSON和XML序列化