博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MVC4 WebAPI
阅读量:6608 次
发布时间:2019-06-24

本文共 8022 字,大约阅读时间需要 26 分钟。

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

(一)环境准备

本机的环境是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
allModeList = new List
(); public IEnumerable
GetAll() { return allModeList; } public IEnumerable
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
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                         $('
  • ', { 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 $('
  • ', { 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
    FindAll() [HttpGet] public IEnumerable
    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
    upDataList = allModeList.FindAll((mode) => { if (mode.ModeKey == key) return true; return false; }); foreach(var mode in upDataList) { mode.ModeValue = value; } return upDataList.Count; }

    ******************************************************************************

    转载地址:http://uuiso.baihongyu.com/

    你可能感兴趣的文章
    【BZOJ 1901】Dynamic Rankings
    查看>>
    阿里架构师都在学的知识体系
    查看>>
    PAT (Advanced Level) 1028. List Sorting (25)
    查看>>
    【摘】人生苦短, 每日python
    查看>>
    【转】聚集索引和非聚集索引的区别
    查看>>
    【转】mac os 安装php
    查看>>
    Android -- OkHttp的简单使用和封装
    查看>>
    软件工程_第二次作业
    查看>>
    C# DllImport的用法
    查看>>
    Github-Client(ANDROID)开源之旅(二) ------ 浅析ActionBarSherkLock
    查看>>
    no identities are available for signing
    查看>>
    javascript 和 jquery插件开发
    查看>>
    Linux Shell文件差集
    查看>>
    eclipse中如何去除警告:Class is a raw type. References to generic type Class<T> should be parameterized...
    查看>>
    Gradle脚本基础全攻略
    查看>>
    Django模版中的过滤器详细解析 Django filter大全
    查看>>
    Linux中使用pwconv实现passwd中密码到shadow
    查看>>
    MongoDB C++ gridfs worked example
    查看>>
    Visual Studio 2017各版本安装包离线下载
    查看>>
    C#线程安全的那些事
    查看>>