MVC4 WebAPI(一)

不管是因为什么原因,结果是在新出的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;
        }

时间: 2024-08-25 12:36:32

MVC4 WebAPI(一)的相关文章

MVC4 WebAPI中如何返回一张图片

public HttpResponseMessage Get(string imageName, int width, int height) { Image img = GetImage(imageName, width, height); MemoryStream ms = new MemoryStream(); img.Save(ms, System.Drawing.Imaging.ImageFormat.Png); HttpResponseMessage result = new Htt

MVC4 WebAPI(一)(转)

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

MVC4 WebAPI(二)——Web API工作方式

在上篇文章中和大家一起学习了建立基本的WebAPI应用,立刻就有人想到了一些问题:1.客户端和WebService之间文件传输2.客户端或者服务端的安全控制要解决这些问题,要了解一下WebAPI的基本工作方式. (一)WebAPI中工作的Class 在MVC中大家都知道,获取Request和Response使用HttpRequest和HttpResponse两个类,在WebAPI中使用两外两个类:HttpRequestMessage 和HttpResponseMessage,分别用于封装Requ

MVC4 WebApi开发中如果想支持Session请做好如下几个方面的问题

1.在WebApiConfig中建立建立HttpControllerHandler和HttpControllerRouteHandler 并覆写它 public class SessionRouteHandler : HttpControllerHandler,IRequiresSessionState { public SessionRouteHandler(RouteData routeData) : base(routeData) { } } public class SessionCon

MVC4 WebAPI POST数据问题

api [HttpPost] public string PostAvartos(Test model) { if (model != null) { LoggerHelper.WriteInfo(model.id + " " + model.name); } else { LoggerHelper.WriteInfo("error"); } return ""; } 实体类 public class Test { public int id {

MVC4 WebApi

using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using testWebApi.Models; namespace testWebApi.Controllers { public class ValuesController : ApiController { // GET api/

Asp.Net MVC4开发一:概要

之前为写Asp.Net MVC4而写了Linq应用系列: Linq技术一:Linq to SQL和Devart Linq to SQL Model Linq技术二:Linq to XML及xml增删改查的不同实现方式 Linq技术三:Linq to Object 和生成数据表的扩展方法 Linq技术四:动态Linq技术 -- Linq.Expressions 现在开始写Asp.Net MVC4的系列应用, 主要方面包括: 1. Entity Framework在Asp.Net MVC4中的应用.

WebApi与手机客户端通信安全机制

WebApi与手机客户端通信安全机制 最近公司有几个项目需要开发手机客户端,服务器端选用WebApi,那么如何保证手机客户端在请求服务器端时数据不被篡改,如何保证一个http请求的失效机制,下面总结一下我们在项目中针对这两个问题的解决方案. 基本思路如下: 用户在成功登陆app客户端之后,手机客户端向服务器端发出的所有的http请求在请求头(HttpHeader)上都会带上下面三个参数:1.Uid(用户ID),2.Ts(时间戳),3.Sign(签名).其中Ts是当前时间减去1970-1-1得到的

ASP.NET MVC WEBAPI第一次接触

asp.net 的MVC4 WEBAPI的出现已经有段时间了.最近因为做自己的一些小玩儿,要做一个API,正好可以学习一下这个WEBAPI. WEBAPI项目的创建我就不啰嗦,先来看看webapi的路由配置吧 config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Option