为什么80%的码农都做不了架构师?>>>   

不管是因为什么原因,结果是在新出的MVC中,增加了WebAPI,用于提供REST风格的WebService,个人比较喜欢REST风格的WebService,感觉比SOAP要轻量级一些,而且对客户端的要求也更少,更符合网络数据传输的一般模式,客户端完全摆脱了代理和管道来直接和WebService进行交互,具体的区别可以参见Web 服务编程,REST 与 SOAP

(一)环境准备

本机的环境是XP+VS2010,需要安装VS2010 SP1升级包,MVC4升级包,Vs2010安装SP1后会影响SQLServer2008的自动提示功能,需要在安装补丁或插件,安装成功后可以新建如下的 MVC WebAPI 项目

(二)概览

新生成的WebAPI项目和典型的MVC项目一样,包含主要的Models,Views,Controllers等文件夹和Global.asax文件

Views对于WebAPI来说没有太大的用途,Models中的Model主要用于保存Service和Client交互的对象,这些对象默认情况下会被转换为Json格式的数据进行传输,Controllers中的Controller对应于WebService来说是一个Resource,用于提供服务。和普通的MVC一样,Global.asax用于配置路由规则

(三)Models

和WCF中的数据契约形成鲜明对比的是,MVC WebAPI中的Model就是简单的POCO,没有任何别的东西,如,你可以创建如下的Model

public class TestUseMode{public string ModeKey{get;set;}public string ModeValue { get; set; }}

注意:Model必须提供public的属性,用于json或xml反序列化时的赋值

(四)Controllers

MVC WebAPI中的Controllers和普通MVC的Controllers类似,不过不再继承于Controller,而改为继承API的ApiController,一个Controller可以包含多个Action,这些Action响应请求的方法与Global中配置的路由规则有关,在后面结束Global时统一说明

(五)Global

默认情况下,模板自带了两个路由规则,分别对应于WebAPI和普通MVC的Web请求,默认的WebAPI路由规则如下

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

可以看到,默认路由使用的固定的api作为Uri的先导,按照微软官方的说法,用于区分普通Web请求和WebService的请求路径:

Note: The reason for using "api" in the route is to avoid collisions with ASP.NET MVC routing. That way, you can have "/contacts" go to an MVC controller, and "/api/contacts" go to a Web API controller. Of course, if you don't like this convention, you can change the default route table.

可以看到,默认的路由规则只指向了Controller,没有指向具体的Action,因为默认情况下,对于Controller中的Action的匹配是和Action的方法名相关联的:

具体来说,如果使用上面的路由规则,对应下面的Controller:

public class TestController : ApiController{public static List<TestUseMode> allModeList = new List<TestUseMode>();public IEnumerable<TestUseMode> GetAll(){return allModeList;}public IEnumerable<TestUseMode> GetOne(string key){return allModeList.FindAll((mode) => { if (mode.ModeKey.Equals(key)) return true; return false; });}public bool PostNew(TestUseMode mode){allModeList.Add(mode);return true;}public int Delete(string key){return allModeList.RemoveAll((mode) => { if (mode.ModeKey == key) return true; return false; });}public int DeleteAll(){return allModeList.RemoveAll((mode) => { return true; });}public int PutOne(string key, string value){List<TestUseMode> upDataList = allModeList.FindAll((mode) => { if (mode.ModeKey == key) return true; return false; });foreach(var mode in upDataList){mode.ModeValue = value;}return upDataList.Count;}}

则,会有下面的对应关系:

简单使用JS调用上面提供的数据接口

1         function getAll() {2             $.ajax({3                 url: "api/Test/",4                 type: 'GET',5                 success: function (data) {6                     document.getElementById("modes").innerHTML = "";7                     $.each(data, function (key, val) {8                         var str = val.ModeKey + ': ' + val.ModeValue;9                         $('<li/>', { html: str }).appendTo($('#modes'));
10                     });
11                 }
12             }).fail(
13             function (xhr, textStatus, err) {
14                 alert('Error: ' + err);
15             });
16         }
17
18
19
20         function add() {
21
22             $.ajax({
23                 url: "api/Test/",
24                 type: "POST",
25                 dataType: "json",
26                 data: { "ModeKey": document.getElementById("txtKey").value, "ModeValue": document.getElementById("txtValue").value },
27                 success: function (data) {
28                     getAll();
29                 }
30             }).fail(
31             function (xhr, textStatus, err) {
32                 alert('Error: ' + err);
33             });
34
35         }
36
37         function find() {
38
39             $.ajax({
40                 url: "api/Test/" + document.getElementById("txtFindKey").value,
41                 type: 'GET',
42                 success: function (data) {
43                     document.getElementById("modes").innerHTML = "";
44                     $.each(data, function (key, val) {
45                         var str = val.ModeKey + ': ' + val.ModeValue;
46                         $('<li/>', { html: str }).appendTo($('#modes'));
47                     });
48                 }
49             }).fail(
50             function (xhr, textStatus, err) {
51                 alert('Error: ' + err);
52             });
53         }
54
55         function removeAll() {
56             $.ajax({
57                 url: "api/Test/",
58                 type: 'DELETE',
59                 success: function (data) {
60                     document.getElementById("modes").innerHTML = "";
61                     getAll();
62                 }
63             }).fail(
64             function (xhr, textStatus, err) {
65                 alert('Error: ' + err);
66             });
67         }
68
69         function remove() {
70             $.ajax({
71                 url: "api/Test/"+document.getElementById("txtRemoveKey").value,
72                 type: 'DELETE',
73                 success: function (data) {
74                     document.getElementById("modes").innerHTML = "";
75                     getAll();
76                 }
77             }).fail(
78             function (xhr, textStatus, err) {
79                 alert('Error: ' + err);
80             });
81         }
82
83         function update() {
84             $.ajax({
85                 url: "api/Test/",
86                 type: 'PUT',
87                 dataType: "json",
88                 data: { "key": document.getElementById("txtUpdateKey").value, "value": document.getElementById("txtUpdateValue").value },
89                 success: function (data) {
90                     document.getElementById("modes").innerHTML = "";
91                     getAll();
92                 }
93             }).fail(
94             function (xhr, textStatus, err) {
95                 alert('Error: ' + err);
96             });
97         }

这样就实现了最基本的CRUD操作。

(六)路由规则扩展

和普通的MVC一样,MVC WebAPI支持自定义的路由规则,如:在上面的操作中,路由规则使用

"api/{controller}/{id}"

则限定了使用GET方式利用URL来传值时,controller后面的接收参数名为id,但是在Controller中,GetOne方法的接收参数名为key,是不会被匹配的,这是只需要新增一个新的路由规则,或修改原先的路由规则为:

"api/{controller}/{key}"

当然,可以对路由进行更深的扩展,如:扩展成和普通MVC一样的路由:

"api/{controller}/{action}/{id}"

这样,就要求同时使用Action和HTTP方法进行匹配
当然,根据微软的说法,这种使用是不被推荐的,因为这不符合大家对WebService的一般认知:

For a RESTful API, you should avoid using verbs in the URIs, because a URI should identify a resource, not an action.

(七)使用Attribute声明HTTP方法

有没有感觉默认的使用方法名来匹配HTTP Method的做法很傻??或者我有一些方法是自己用的,不想暴露出来,又该怎么办?还是使用attribute做这些工作感觉优雅一些,比如,上面的Action我可以更改为:

[HttpGet]public IEnumerable<TestUseMode> FindAll()[HttpGet]public IEnumerable<TestUseMode> FindByKey(string key)[HttpPost]public bool Add(TestUseMode mode)[HttpDelete]public int RemoveByKey(string key)[HttpDelete]public int RemoveAll()[HttpPut]public int UpdateByKey(string key, string value)[NonAction]  public string GetPrivateData()

当然,我只列出了方法名,而不是这些方法真的没有方法体...方法体是不变的,NoAction表示这个方法是不接收请求的,即使以GET开头。
如果感觉常规的GET,POST,DELETE,PUT不够用,还可以使用AcceptVerbs的方式来声明HTTP方法,如:

[AcceptVerbs("MKCOL", "HEAD")]public int UpdateByKey(string key, string value){List<TestUseMode> upDataList = allModeList.FindAll((mode) => { if (mode.ModeKey == key) return true; return false; });foreach(var mode in upDataList){mode.ModeValue = value;}return upDataList.Count;}

******************************************************************************
作者:王坤 
出处:http://www.cnblogs.com/wk1234

转载于:https://my.oschina.net/garyun/blog/602725

MVC4 WebAPI(一)相关推荐

  1. MVC4 WebAPI

    不管是因为什么原因,结果是在新出的MVC中,增加了WebAPI,用于提供REST风格的WebService,个人比较喜欢REST风格的WebService,感觉比SOAP要轻量级一些,而且对客户端的要 ...

  2. Retrofit2.0+ .Net MVC4(WebApi) 上传多张图片

    最近在做Android项目,使用的是MVP+Retrofit+rxjava+dagger的项目架构,RestFul 服务使用的.Net平台的WebApi.由于业务中需要有多文件上传的功能.所以在这里记 ...

  3. IOS5开发-http get/post调用mvc4 webapi互操作(图片上传)

    目前最流行的跨平台交互是采用http协议通过JSON对象进行互操作.这种方式最简单,也很高效.webservice+xml的方式似乎已经过时. 下面是我做的一个例子 webapi的代码 View Co ...

  4. ASP.NET Web API之消息[拦截]处理(转)

    出处:http://www.cnblogs.com/Leo_wl/p/3238719.html 标题相当难取,内容也许和您想的不一样,而且网上已经有很多这方面的资料了,我不过是在实践过程中作下记录.废 ...

  5. 深圳面试一周记录——.NET(B/S)开发

    个人简单信息:2011年毕业,最高学历大专,最近一份工作在广州:有做架构设计经验,有一年的带团队(10人左右)经验:互联网和行业软件公司都待过. 为免不必要的争论,本文说地址的就不说公司行业,说公司行 ...

  6. 国内 Mono 相关文章汇总

    一则新闻<软件服务提供商Xamarin融资1200万美元>,更详细的内容可以看Xamarin的官方博客Xamarin raises $12M to help you make better ...

  7. 上周热点回顾(7.22-7.28)

    热点随笔: · 我要开始转方向了C# To Java(吴庭智) · 再见,上海~非主流码农在上海的9年心路历程(枫) · [激励机制]浅谈内部竞争--如何让你的员工玩命干活?(1-2-3) · 我的权 ...

  8. 上周热点回顾(7.29-8.4)

    热点随笔: · .NET框架设计-常被忽视的C#设计技巧(王清培) · 那些年黑了你的微软BUG(Dennis Gao) · [商业源码]生日大放送-Newlife商业源码分享(asxinyu) · ...

  9. mvc4中的 webapi 的使用方式

    目录 一:简单介绍什么是Web api 二:怎么定义的 Post Get Put 和 Delete 三:简单使用,直接从前台传递一个类到后台接收 四:其他获取值的方式 一:简单介绍什么是Web api ...

最新文章

  1. 日常安排php,PHP日常开发小技巧
  2. magento 为用户注册增加一个字段(转)
  3. 【Python】Pandas宝藏函数-concat()
  4. Boost:bind绑定和或||的测试程序
  5. Serekh塞拉赫资源包背后的创作过程
  6. 天正建筑lisp编程接口_编程思想|面向过程的结构化、面向对象的抽象化、泛型编程...
  7. 从 0.99999... = 1 到芝诺悖论
  8. php加密密码解析,php密码加密解密
  9. python常用的库介绍_Python的标准库介绍与常用的第三方库
  10. 2021动画渲染农场排名出炉,渲染101综合领先,赛诚和瑞云Renderbus紧随其后!
  11. docker使用阿里云的镜像加速器的地址
  12. ABSOLUTE评估肿瘤纯度
  13. Maven中创建同名项目:Failed to create a Maven project解决(IntelliJ IDEA)
  14. 阿里百度腾讯等34家企业获年度互联网经济大奖
  15. AI技术是什么?AI对生活的影响有哪些?
  16. MySQL 删除数据后自增长主键id依旧占用问题
  17. 一键解决PPT的动画播放和动画排序问题!
  18. 需求定律的4个准则——《可以量化的…
  19. 未来生活里掌握计算机技术的重要性,浅谈计算机教育重要性的几点理解.doc
  20. 消息服务MNS和消息队列ONS产品对比

热门文章

  1. Jenkins修改插件下载地址为国内下载地址与安装中文插件
  2. 若依前后端分离版源码分析-前端头像上传后传递到后台以及在服务器上存储和数据库存储设计
  3. springboot-自动配置原理
  4. 国内常用的学习flutter地址
  5. 在Flutter中解析复杂的JSON(一篇顶十篇)
  6. 使用 Gitee 进行代码管理(包括本地仓库如何同时关联Git和Gitee)
  7. 7-25日牛客网刷题 未知点、错题 集合
  8. python123期末测试第十周答案_Python语言设计_章节测验,期末考试,慕课答案查询公众号...
  9. 多部门数据分析需求,如何满足?
  10. 互联网推广方案:如何提高企业网站排名!