本次分两个大方向去讲解Web Api,1、如何实现Web Api?2、如何Android端如何调用Web Api?对于Web Api是什么?有什么优缺点?为什么用WebApi而不用Webservice?这些问题都不去解答,百度一下,关于这方面的资料很多,就不再去啰嗦。

一、如何在web端实现WebApi

(1)如何新建一个WebApi?

在上一章中,讲到我们项目用的是.net 4.5,开发工具是Visual Studio 2012,在Visual Studio 2012中新建MVC4项目,选择Web API,然后项目生成,如下图一、图二、图三所示, 和普通的MVC项目相比,它继承了ApiController,然后我们运行一下项目,在浏览器里输入http://localhost:56091/api/values/get?id=5,如图四所示,即成功调用了项目默认写的Get方法实例,有数据返回即表示调用成功!

(图一)

(图二)

(图三)

(图四)

(2)Get和Post数据?

(2.1) Get方法

具体什么是Get就不再啰嗦了,可以自己百度查看, 使用 [HttpGet]标识,当然也可以不用加,只需要方法名用Get开头,Get方法是使用Url参数传递的,不能接收实体参数,如:http://localhost:56091/api/values/get?id=5,id即是参数,当然也可以多参数,如:http://localhost:56091/api/values/get?id=5&name=tim ,默认参数使用[FromUri]

Get是有长度限制的,参数不能过多,而且参数暴露在外面,容易被人很方便的截取。

(2.2)Post方法

使用 [HttpPost]方式传递,当然也可以不用加,只需要方法名用Post开头,Post方法可以使用Url传递参数,也可以用Body传递参数,默认参数使用[FromUri],可以加[FromBody]接收body里传递的参数,但是有问题的是,我使用[FromBody]方式,参数为空,根本接收不动值,上网查了资料,很多人遇到问题,不知道是不是Web Api本身的问题,无奈只好使用下面最原始的方式了,获取Body的值了。

1
2
3
4
5
6
7
HttpContextBase context = (HttpContextBase)Request.Properties[MS_HttpContext];//获取传统context
HttpRequestBase request = context.Request;//定义传统request对象
string name = request.Form.Keys[0];
if (name == null)
{
    name = request.Form[0];
}

另外Post的方法不能直接在浏览器里敲地址获取数据,调试起来不是很方便,所以用了一个工具,火狐浏览器可以安装一个插件,叫Poster,如下图六所示,测试起来很方便。

(图五)

(图六)

(3)Json数据格式?

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。

Json数据格式传输是目前接口数据传输主流,本次我们的项目也是使用Json格式数据,我们所有的接口参数都是统一的参数名,后面跟的是Json格式字符串,如:http://localhost:8010/api/MobileInfo/Get_Welcome? params=JsonString,这是接口的调用,接口返回结果也是Json格式。

如下图七所示,使用Newtonsoft.Json类库,这是VS项目集成的类库,可以很方便的使用JsonConvert.SerializeObject(value)方法,将object对象转换为Json格式。

(图七)

1
2
3
//step2:参数反序列化
T transferObj = default(T);
transferObj = Newtonsoft.Json.JsonConvert.DeserializeObject<t>(JsonString);</t>

(4) 路由的配置

如下图八所示,默认路由配置是这样,只会找到Controller,不用根据Action去分配地址,所以相同Controller下只会找到Get方法或Post方法,不管你方法名是否相同,这样很明显不能满足我们的需求,如果想以Action去标识地址,就用下面代码配置:

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

(图八)

二、如何在Android端调用WebApi

(1)调用web Api的Get方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void getAnnouncement(final Object reqTag, final WSAnnouncementListCb cb) {
 
     //需要调用WebApi的Url地址  参数用UTF-8编码        String url = Constants.WEB_BASE_URL
            + MobileInfo/Get_AnnouncementList?JsonString=
            + Utils.getEncodingParamsString((Object) UserManager.getInstance()
                    .getLoginedUserInfo());
 
    //使用Request对象,请求数据  Mdthod.Get WsAnnouncementListRsp.class接收结果的对象实体类        GsonRequest<wsannouncementlistrsp> gsonRequest = new GsonRequest<wsannouncementlistrsp>(
            Method.GET, url, WSAnnouncementListRsp.class,
            new Response.Listener<wsannouncementlistrsp>() {
                @Override
                public void onResponse(WSAnnouncementListRsp rsp) {
            //返回的Json格式数据,经过反序列化后的对象实体                        if (cb != null) {
                        cb.onResponse(Utils.stringToInteger(rsp.message.ResultCode), rsp);
                    }
                }
 
            }, errorListener(true));
 
    gsonRequest.setRequestTag(reqTag);
 
    RequestManager.addRequest(gsonRequest, reqTag);
}</wsannouncementlistrsp></wsannouncementlistrsp></wsannouncementlistrsp>

Android反序列化Json的方法:

当然下面代码中包含判断Token是否过期,过期之后重新登录,因为判断Token是否过期是每个App接口都可能要考虑的事情,所以就没有删除,以供大家参考。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//Response的时候,返回解析后的对象
 protected Response<t> parseNetworkResponse(NetworkResponse response) {
        try {
 
            //接收到的Json格式数据字符串
            String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            //如果有转义字符就替换她
            json = json.substring(1, json.length() - 1);
            json = json.replace(\, );
            Log.I(L, Response type: + mClazz.getName() + Parsed Json Buffer:  + json);
             
            //反序列化Json数据
            WSBaseResponse baseResponse = (WSBaseResponse) mGson.fromJson(json, mClazz);
            //判断Token是否过期
            if (Utils.stringToInteger(baseResponse.message.ResultCode) == Constants.ERR_TOKEN_INVALID) {
//                Log.I(L, get token status: + UserManager.getInstance().getTokenStatus());
//                if (UserManager.getInstance().getTokenStatus() != TOKEN_STATUS.TOKEN_GETTING) {
//                    Log.I(L,set token status: + TOKEN_STATUS.TOKEN_EXPIRED);
//                    UserManager.getInstance().setTokenStatus(TOKEN_STATUS.TOKEN_EXPIRED);
//                }
 
                synchronized (GsonRequest.class) {
                    if (UserManager.getInstance().getTokenStatus() != TOKEN_STATUS.TOKEN_GETTING) {
                        Log.I(L,  relogin ...);
                                            
                        RequestManager.addCachedRequest(this);
 
                        UserManager.getInstance().relogin(new OnLoginListener() {
 
                            @Override
                            public void onLogin(int result, String message) {
                                if (result == UserManager.LOGIN_RESULT_OK) {
                                    Log.I(L, Login suceesss);
                                     
                                    UserManager.getInstance().setTokenStatus(TOKEN_STATUS.TOKEN_OK);
                                   
                                     
                                } else {
                                    Log.I(L,Login failed...);
                                    // Show login activity
                                    UserManager.getInstance().setTokenStatus(TOKEN_STATUS.TOKEN_FAIL);
                                    MyActivityManager.getInstance().finishAllActivity();
                                    showLoginActivity();
                                }
                            }
                        });
                    } else {
                        //
                        Log.I(L, prepare resend request);
                       // reSendRequest();
                        RequestManager.addCachedRequest(this);
                    }
 
                }
 
                return Response.error(new TokenExpiredError());
            } else {
 
                //返回泛型对象
                return Response.success((T) baseResponse/*
                                                         * mGson.fromJson(json,
                                                         * mClazz)
                                                         */,
                        HttpHeaderParser.parseCacheHeaders(response));
            }
 
        } catch (UnsupportedEncodingException e) {
            Log.E(L, response parse error: + mClazz.getName());
            return Response.error(new ParseError(e));
        } catch (JsonSyntaxException e) {
            Log.E(L, response parse error: + mClazz.getName());
            return Response.error(new ParseError(e));
        }
    }
</t>

(2)调用web Api的Post方法

放在Url里的和Get方法一样调用,只是传参的时候,把Method.Get改为Method.Post方式,

因此主要讲Post的Body方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void updateUserInfo(final Object reqTag, final WSUpdateUserInfoReq req,
        final WSUpdateUserInfoCb cb) {
 
    setUserIdAndTokenForReq(req);
 
    // post Url不带任何参数
    String url = Constants.WEB_BASE_URL + MobileInfo/Save_EmployeeInfo;
//req是参数
    GsonRequest<wscommonrsp> gsonRequest = new GsonRequest<wscommonrsp>(
            Method.POST, url,Utils.getEncodingParamsString((Object) req), WSCommonRsp.class,
            null, new Response.Listener<wscommonrsp>() {
                @Override
                public void onResponse(WSCommonRsp rsp) {
                    if (cb != null) {
                        cb.onResponse(Utils.stringToInteger(rsp.message.ResultCode), rsp);
                    }
                }
 
            }, errorListener(true));
 
    gsonRequest.setRequestTag(reqTag);
 
    RequestManager.addRequest(gsonRequest, reqTag);
 
}</wscommonrsp></wscommonrsp></wscommonrsp>

以上就是App接口的实现和接口在Android中的调用方法,我提供的都是一些伪代码,主要是讲解功能实现的思想和用到哪些重要的类方法。下章则正式学习Android开发,看一个零基础的菜鸟如何快速上手做开发的。

android移动开发学习笔记(二)神奇的Web API的更多相关文章

  1. python-django开发学习笔记二

    1.简述 1.1 开发环境 该笔记所基于的开发环境为:windows8.python2.7.5.psycopg2-2.4.2.django1.5.4.pyCharm-2.7.3.以上所描述的软件.插件 ...

  2. Android Studio安卓学习笔记(二)Android项目结构

    上一篇代码,我们学习了Android的功能以及如何用Android Studio开发第一个安卓程序.下面就要介绍Android项目结构.为日后学习打基础. 一:Android项目结构 打开MyFris ...

  3. Android应用开发学习笔记之播放音频

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android支持常用音视频格式文件的播放,本文我们来学习怎样开发Android应用程序对音视频进行操作. Andr ...

  4. Android应用开发学习笔记之事件处理

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android提供的事件处理机制分为两类:一是基于监听的事件处理:二是基于回调的事件处理.对于基于监听的事件处理,主 ...

  5. Android应用开发学习笔记之Fragment

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Fragment翻译成中文就是“碎片”.“片断”的意思,Fragment通常用来作为一个Activity用户界面的一 ...

  6. 软件开发学习笔记 <二>软件开发模型、Up、Rup、敏捷Up

    软件开发过程(process) 是一个将用户需求转化为软件系统所需要的活动的集合. 软件生命周期(SDLC,Software Devlopment Life Cycle) 软件从孕育.诞生.成长.成熟 ...

  7. Android应用开发学习笔记之菜单

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android中的菜单分为选项菜单(OptionMenu)和上下文菜单(Context Menu).通常使用菜单资源 ...

  8. Android应用开发学习笔记之Intent

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Intent是什么呢?来看Android官网上的定义: An intent is an abstractdescri ...

  9. Android应用开发学习笔记之AsyncTask

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 在上一篇文章中我们学习了多线程和Handler消息处理机制,如果有计算量比较大的任务,可以创建一个新线程执行计算工作 ...

随机推荐

  1. 可编辑DIV (contenteditable="true") 在鼠标光标处插入图片或者文字

    近期需开发一个DIV做的编辑器,插入表情图片可直接预览效果,仔细参考了下百度贴吧的过滤粘贴过来文件的THML代码,自己整理了下.写出来只是和大家分享下,我自己也不大懂,经过努力,幸好搞定. 蛋疼的事情 ...

  2. 【最新】让快捷方式 实现相对路径——非.bat方式实现

    快捷方式一般是使用绝对路径的,但并不是不能使用相对路径,系统为普通用户考虑一般默认使用绝对路径,这样的结果是:只要目标文件(不论是文件夹.程序.文档,也包括快捷方式)绝对位置不变,我们创建的快捷方式基 ...

  3. ckedit 在源码模式下插入文本

    ckedit的源码模式下是禁用insertText方法的 ,下面是解决方案 if(CKEDITOR.instances[Itemname].mode=='wysiwyg'){ CKEDITOR.ins ...

  4. Mongodb 集群搭建以及常见错误

    Mongodb 集群搭建以及常见错误 1 关于Replica Sets +Sharding(主从复制加分片)搭建,不这详细去说,网上有很多,大部分的例子就三台服务器之间做主从复制,分2个shard,架 ...

  5. 使用C#开发ActiveX控件

    使用C#开发ActiveX控件(新) 前言 ActiveX控件以前也叫做OLE控件,它是微软IE支持的一种软件组件或对象,可以将其插入到Web页面中,实现在浏览器端执行动态程序功能,以增强浏览器端的动 ...

  6. VIM批量文件查找和替换

    使用vim时间不长,linux命令行下常用的文本编辑工具,所以需要掌握一些基本的用法.很多不会的不是百度就谷歌,总有你想要的答案. 1. 批量文件查找内容 vimgrep 比如在当前目录下查找带有“a ...

  7. Servle中的会话管理

    最近整理了下会话管理的相关笔记,以下做个总结: 一.会话管理(HttpSession) 1.Web服务器跟踪客户状态的四种方法: 1).使用Servlet API的Session机制(常用) 2).使 ...

  8. php memcached+Mysql(主从)

    /* index.php   程序入口,用来构造sql(如查询,更新) config.php  配置参数(memcache,mysql) init.php    封装memcached操作(memca ...

  9. 添加第三方类库造成的Undefined symbols for architecture i386:编译错误

    1.原因: 如果是源码编译的话,一般就只某些头文件没有添加到src编译里面.但是对于添加库编译,一般是库的编译路径设置不正确(比如arm的版本.模拟器或者真机的不同版本库引用错误或者重复引用一起编译器 ...

  10. hdu 4515 年月份模拟题

    小Q系列故事——世界上最遥远的距离 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) ...