摘自http://blog.csdn.net/fangxing80/article/details/7318289

在刚刚发布的 ASP.NET MVC 4 中,有一个值得注意的新特性——Web Api,微软官方的介绍是:

ASP.NET MVC 4 中包含了Web API 它能够构建HTTP服务以支撑更广泛的客户端,包括浏览器,手机和平板电脑的框架。
ASP.NET Web API是非常棒的构建服务的框架,遵循REST架构风格,而且它支持的RPC模式。

从 .NET 3.5 开始 WCF 已经支持用 WebHttpBinding 构建 RESTful Web 服务,基于 WCF 框架的 Web Api 还是建立在 WCF Message 栈上,因为 REST 的工作原理有所不同,它不需要依赖 SOAP 协议,因此 WCF 消息管道对于它经过了特殊的消息优化。但 REST 集成在 WCF 消息管道上还是不理想,所以微软提出在 ASP.NET 平台上构建REST服务,也就有了现在 ASP.NET MVC 4 中的 Web Api。

引用 WCF 在 Codeplex 上的声明:
Announcement: WCF Web API is now ASP.NET Web APIASP.NET Web API released with ASP.NET MVC 4 Beta. 
The WCF Web API and WCF support for jQuery content on this site wll removed by the end of 2012.
 
如果对 REST WCF 框架熟悉的童鞋,可以参看下面的 WCF Web Api 到 ASP.NET Web Api 的映射表:

WCF Web API ASP.NET Web API
Service Web API controller
Operation Action
Service contract Not applicable
Endpoint Not applicable
URI templates ASP.NET Routing
Message handlers Same
Formatters Same
Operation handlers Filters, model binders

下面来看看如何使用 ASP.NET Web Api (使用的是 VS11 Beta 版)
(1) 创建 ASP.NET MVC 4 工程时选择 Web Api

创建出的工程中,Controllers 目录下会有一个 ValuesController.cs 注意它继承于 ApiController

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net.Http;
  5. using System.Web.Http;
  6. namespace MvcApplication1.Controllers
  7. {
  8. public class ValuesController : ApiController
  9. {
  10. // GET /api/values
  11. public IEnumerable<string> Get()
  12. {
  13. return new string[] { "value1", "value2" };
  14. }
  15. // GET /api/values/5
  16. public string Get(int id)
  17. {
  18. return "value";
  19. }
  20. // POST /api/values
  21. public void Post(string value)
  22. {
  23. }
  24. // PUT /api/values/5
  25. public void Put(int id, string value)
  26. {
  27. }
  28. // DELETE /api/values/5
  29. public void Delete(int id)
  30. {
  31. }
  32. }
  33. }

在 Global.cs 中,注册了 Api 的 Url Map: api/{controller}/{id} 每个"Action"是通过 Http谓词(GET/POST/PUT/DELETE)映射的。

  1. public static void RegisterRoutes(RouteCollection routes)
  2. {
  3. routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  4. routes.MapHttpRoute(
  5. name: "DefaultApi",
  6. routeTemplate: "api/{controller}/{id}",
  7. defaults: new { id = RouteParameter.Optional }
  8. );
  9. routes.MapRoute(
  10. name: "Default",
  11. url: "{controller}/{action}/{id}",
  12. defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
  13. );
  14. }

(2) 增加一个自定义 Model

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. namespace MvcApplication1.Models
  6. {
  7. public class Task
  8. {
  9. public string Id { get; set; }
  10. public string Title { get; set; }
  11. public string Content { get; set; }
  12. public int Status { get; set; }
  13. }
  14. }

(3) 增加一个自定义 Repository

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using MvcApplication1.Models;
  6. namespace MvcApplication1.Repositories
  7. {
  8. public class TaskRepository
  9. {
  10. private List<Task> _tasks;
  11. public TaskRepository()
  12. {
  13. _tasks = new List<Task> {
  14. new Task { Id="T001", Title="title1", Content="content1" },
  15. new Task { Id="T002", Title="title2", Content="content2" },
  16. new Task { Id="T003", Title="title3", Content="content3" },
  17. new Task { Id="T004", Title="title4", Content="content4" },
  18. };
  19. }
  20. public IEnumerable<Task> GetAll()
  21. {
  22. return _tasks;
  23. }
  24. public Task FindById(string id)
  25. {
  26. return _tasks.FirstOrDefault(t => t.Id == id);
  27. }
  28. public void Add(Task task)
  29. {
  30. _tasks.Add(task);
  31. }
  32. public void RemoveById(string id)
  33. {
  34. var task = _tasks.FirstOrDefault(t => t.Id == id);
  35. if (task != null)
  36. _tasks.Remove(task);
  37. }
  38. }
  39. }

(4) 增加 TaskController

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net.Http;
  5. using System.Web.Http;
  6. using MvcApplication1.Models;
  7. namespace MvcApplication1.Controllers
  8. {
  9. public class TasksController : ApiController
  10. {
  11. private Repositories.TaskRepository _taskRepository = new Repositories.TaskRepository();
  12. // GET /api/tasks
  13. public IQueryable<Task> Get()
  14. {
  15. return _taskRepository.GetAll().AsQueryable();
  16. }
  17. // GET /api/tasks/5
  18. public Task Get(string id)
  19. {
  20. return _taskRepository.FindById(id);
  21. }
  22. // POST /api/tasks
  23. public void Post(Task task)
  24. {
  25. _taskRepository.Add(task);
  26. }
  27. // DELETE /api/tasks/5
  28. public void Delete(string id)
  29. {
  30. _taskRepository.RemoveById(id);
  31. }
  32. }
  33. }

运行:

同样,客户端可以通过 Http Header 的 Accept 指定返回数据的格式。默认是支持:appliction/xml 和 application/json 
当想返回比如 image/jpeg 这样的图片格式时,需要添加 MediaTypeFormatter

比如:当指定某个 Task 时,通过指定 Accept : image/jpeg 获取该 Task 的图片信息。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net.Http.Formatting;
  5. using System.Web;
  6. using MvcApplication1.Models;
  7. namespace MvcApplication1.Repositories
  8. {
  9. public class TaskPictureFormatter : MediaTypeFormatter
  10. {
  11. protected override bool CanWriteType(Type type)
  12. {
  13. return (type == typeof(Task));
  14. }
  15. public TaskPictureFormatter()
  16. {
  17. SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg"));
  18. }
  19. protected override System.Threading.Tasks.Task OnWriteToStreamAsync(Type type, object value,
  20. System.IO.Stream stream, System.Net.Http.Headers.HttpContentHeaders contentHeaders,
  21. FormatterContext formatterContext, System.Net.TransportContext transportContext)
  22. {
  23. var task = value as Task;
  24. if (task != null)
  25. {
  26. var data = System.IO.File.ReadAllBytes(HttpContext.Current.Server.MapPath("~/TaskImages/" + task.Id + ".png"));
  27. return stream.WriteAsync(data, 0, data.Length);
  28. }
  29. else
  30. {
  31. throw new HttpException((int)System.Net.HttpStatusCode.NotFound, "task is not found", null);
  32. }
  33. }
  34. }
  35. }

注意:当找不到对应的图片时,抛出 HttpException 这样可以给客户端更加友好的错误提示。

当输入一个错误的Id:

另外一个强大的功能是 Web Api 的 SelfHost,通过 HttpSelfHostServer 就可以非常方便的将 Web Api 寄宿到 IIS 以外的应用中去了。
作为简单数据交换的应用场景十分有用。

注意工程需要添加以下引用:

  • System.Net.Http
  • System.Web.Extensions
  • System.Web.Http
  • System.Web.Http.Common
  • System.Web.Http.SelfHost
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Web.Http;
  7. using System.Web.Http.SelfHost;
  8. namespace WebApiSelfHostTest
  9. {
  10. class Program
  11. {
  12. static void Main(string[] args)
  13. {
  14. var config = new HttpSelfHostConfiguration("http://localhost:8080");
  15. config.Routes.MapHttpRoute(
  16. "API Default", "api/{controller}/{id}",
  17. new { id = RouteParameter.Optional });
  18. using (HttpSelfHostServer server = new HttpSelfHostServer(config))
  19. {
  20. server.OpenAsync().Wait();
  21. Console.WriteLine("HttpServer is opening, Press Enter to quit.");
  22. Console.ReadLine();
  23. }
  24. }
  25. }
  26. public class Product
  27. {
  28. public int Id { get; set; }
  29. public string Name { get; set; }
  30. public decimal Price { get; set; }
  31. }
  32. public class ProductsController : ApiController
  33. {
  34. public IEnumerable<Product> GetAllProducts()
  35. {
  36. return new List<Product>
  37. {
  38. new Product() { Id = 1, Name = "Gizmo 1", Price = 1.99M },
  39. new Product() { Id = 2, Name = "Gizmo 2", Price = 2.99M },
  40. new Product() { Id = 3, Name = "Gizmo 3", Price = 3.99M }
  41. };
  42. }
  43. }
  44. }


web api (.NET 4.5)的更多相关文章

  1. 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用

    由于ASP.NET Web API具有与ASP.NET MVC类似的编程方式,再加上目前市面上专门介绍ASP.NET Web API 的书籍少之又少(我们看到的相关内容往往是某本介绍ASP.NET M ...

  2. bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序

    也许单页程序(Single Page Application)并不是什么时髦的玩意,像Gmail在很早之前就已经在使用这种模式.通常的说法是它通过避免页面刷新大大提高了网站的响应性,像操作桌面应用程序 ...

  3. Hello Web API系列教程——Web API与国际化

    软件国际化是在软件设计和文档开发过程中,使得功能和代码设计能处理多种语言和文化习俗,在创建不同语言版本时,不需要重新设计源程序代码的软件工程方法.这在很多成熟的软件开发平台中非常常见.对于.net开发 ...

  4. ASP.NET Web API 跨域访问(CORS)

    一.客户端用JSONP请求数据 如果你想用JSONP来获得跨域的数据,WebAPI本身是不支持javascript的callback的,它返回的JSON是这样的: {"YourSignatu ...

  5. Web Api 入门实战 (快速入门+工具使用+不依赖IIS)

    平台之大势何人能挡? 带着你的Net飞奔吧!:http://www.cnblogs.com/dunitian/p/4822808.html 屁话我也就不多说了,什么简介的也省了,直接简单概括+demo ...

  6. Web APi之认证(Authentication)两种实现方式【二】(十三)

    前言 上一节我们详细讲解了认证及其基本信息,这一节我们通过两种不同方式来实现认证,并且分析如何合理的利用这两种方式,文中涉及到的基础知识,请参看上一篇文中,就不再叙述废话. 序言 对于所谓的认证说到底 ...

  7. angular2系列教程(八)In-memory web api、HTTP服务、依赖注入、Observable

    大家好,今天我们要讲是angular2的http功能模块,这个功能模块的代码不在angular2里面,需要我们另外引入: index.html <script src="lib/htt ...

  8. 我这么玩Web Api(二):数据验证,全局数据验证与单元测试

    目录 一.模型状态 - ModelState 二.数据注解 - Data Annotations 三.自定义数据注解 四.全局数据验证 五.单元测试   一.模型状态 - ModelState 我理解 ...

  9. 我这么玩Web Api(一):帮助页面或用户手册(Microsoft and Swashbuckle Help Page)

    前言 你需要为客户编写Api调用手册?你需要测试你的Api接口?你需要和前端进行接口对接?那么这篇文章应该可以帮到你.本文将介绍创建Web Api 帮助文档页面的两种方式,Microsoft Help ...

  10. [译] 在Web API 2 中实现带JSON的Patch请求

    原文链接:The Patch Verb in Web API 2 with JSON 我想在.NET4.6 Web API 2 项目中使用Patch更新一个大对象中的某个字断,这才意识到我以前都没有用 ...

随机推荐

  1. OpenCV2马拉松第14圈——边缘检測(Sobel,prewitt,roberts)

    收入囊中 差分在边缘检測的角色 Sobel算子 OpenCV sobel函数 OpenCV Scharr函数 prewitt算子 Roberts算子 葵花宝典 差分在边缘检測究竟有什么用呢?先看以下的 ...

  2. Riak VClock

    Riak VClock 关于向量时钟的概念.在这里就多讲了,大家能够參照一下Dynamo的论文了解一下,向量时钟在分布式主要用于解决一致性性问题.能够和CRDTs一起看. 以下的源码是參照riak中的 ...

  3. 电子设计省赛--DMA与ADC

    //2014年4月17日 //2014年6月20日入"未完毕" //2014年6月21日 DMA可实现无需cpu控制中断的传输数据保存. 特别是ADC转换多个通道时要用到. 关键是 ...

  4. poj 2446 (二分匹配)

    题意:除了所给的一些点外,问能不能用1*2的矩形覆盖所有的点,矩形间不能重叠. 思路:简单二分匹配,,,,,,, #include<stdio.h> #include<string. ...

  5. 设计模式入门之职责链模式Chain Of Responsibility

    //职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. //实例:申请费用的功能,不同金额的费 ...

  6. 深入浅出:重温JAVA中接口与抽象的区别

    抽象类:声明一个抽象类,就是在类的声明开头.在Class关键字的前面使用关键字abstract 下面定义一个抽象类,代码如下: abstract class A{ abstract void call ...

  7. LR实战之Discuz开源论坛——登录脚本检查点

    在开发Discuz登录脚本时,遇到的一个问题是怎么去验证虚拟用户真正的登录成功,当然,熟悉LoadRunner工具的人就会知道,在脚本中使用检查点,对,没错! 我们知道,LR检查点功能有两种:文本检查 ...

  8. WAS下获取包路径下所有类

    最近做javaweb项目的混淆工作,用到proguard,该工具混淆.jar文件比较方便,故把所有项目代码和配置文件打成jar包, 生成的jar包经过proguard处理后,再次打包(解决progua ...

  9. 【Java基础】static关键字相关

    static关键字特点: 随着类的加载而加载. 优先于对象存在. 被所有对象共享 可以直接被类名调用. 使用注意: 静态方法只能访问静态成员. 但非静态成员可以访问静态成员. 静态方法中不能使用thi ...

  10. PlSql复制角色、权限和添加角色权限

    一.登录你想要复制数据库的用户