微信小程序的Web API接口設(shè)計(jì)及常見接口實(shí)現(xiàn)

微信小程序給我們提供了一個(gè)很好的開發(fā)平臺(tái)僧鲁,可以用于展現(xiàn)各種數(shù)據(jù)和實(shí)現(xiàn)豐富的功能坏挠,通過小程序的請求Web API 平臺(tái)獲取JSON數(shù)據(jù)后站故,可以在小程序界面上進(jìn)行數(shù)據(jù)的動(dòng)態(tài)展示蚕键。在數(shù)據(jù)的關(guān)鍵 一環(huán)中泌豆,我們設(shè)計(jì)和編寫Web API平臺(tái)是非常重要的定庵,通過這個(gè)我們可以實(shí)現(xiàn)數(shù)據(jù)的集中控制和管理,本篇隨筆介紹基于Asp.NET MVC的Web API接口層的設(shè)計(jì)和常見接口代碼的展示踪危,以便展示我們常規(guī)Web API接口層的接口代碼設(shè)計(jì)蔬浙、參數(shù)的處理等內(nèi)容。

1贞远、Web API整體性的架構(gòu)設(shè)計(jì)

我們整體性的架構(gòu)設(shè)計(jì)畴博,包含一個(gè)Web管理后臺(tái)、一個(gè)Web API統(tǒng)一接口層兴革、當(dāng)然還有數(shù)據(jù)庫什么绎晃,另外還有一個(gè)小程序客戶端。整個(gè)架構(gòu)體系還是以我之前隨筆介紹的《整合微信小程序的Web API接口層的架構(gòu)設(shè)計(jì)》內(nèi)容為藍(lán)本


整個(gè)體系以Web API為主提供服務(wù)杂曲,同時(shí)后臺(tái)管理系統(tǒng)通過各種界面維護(hù)著數(shù)據(jù)的增刪改等基礎(chǔ)管理工作庶艾。
Web API的分層,我們可以通過下圖來了解具體的分層結(jié)構(gòu)擎勘。

隨著基于JSON格式的Web API的廣泛應(yīng)用咱揍,越來越多的企業(yè)采用Web API接口服務(wù)層,作為統(tǒng)一接口的核心所在棚饵,也成為Web API核心層煤裙。基于JSON格式的接口噪漾,可以廣泛地硼砰、跨平臺(tái)的應(yīng)用于IOS、安卓等移動(dòng)端欣硼,也可以應(yīng)用在常規(guī)的Web業(yè)務(wù)系統(tǒng)题翰,Winform業(yè)務(wù)系統(tǒng)、微信應(yīng)用、微信小程序等方方面面豹障,因此企業(yè)內(nèi)部形成自己是的一套Web API標(biāo)準(zhǔn)和詳細(xì)的文檔非常重要冯事。
我們可以細(xì)化為下面的架構(gòu)設(shè)計(jì)圖,所有模塊均圍繞著Web API 接口層進(jìn)行擴(kuò)展血公,底層的數(shù)據(jù)存儲(chǔ)對上層的應(yīng)用是完全透明昵仅,我們可以根據(jù)需要拆分各種業(yè)務(wù)數(shù)據(jù)庫,以及使用我們認(rèn)為合適的數(shù)據(jù)庫累魔。



其中我們在Web API接口層上還看到一個(gè)微信消息交互的模塊摔笤,這個(gè)模塊我們?yōu)榱朔奖阌蛎丝诘奶幚恚蚖eb API 是統(tǒng)一放在一起的,它負(fù)責(zé)和騰訊微信服務(wù)器進(jìn)行消息的交互處理,從而實(shí)現(xiàn)各種消息推送處理逾一。

2、基于Asp.NET MVC的Web API接口的實(shí)現(xiàn)

1)GET方式
GET方式寞冯,接口參數(shù)包括有零或一個(gè)參數(shù),以及多個(gè)參數(shù)的方式晚伙,返回的值可以是簡單的字符串等基礎(chǔ)類型吮龄,也可以是復(fù)雜的自定義對象類型等,如下面幾種接口代碼所示咆疗。

        /// <summary>
        /// 簡單的GET方式獲取數(shù)據(jù)
        /// </summary>
        /// <param name="id">字符串ID</param>
        /// <param name="token">接口訪問令牌</param>
        /// <returns>返回字符串值</returns>
        [HttpGet]
        public string Test(string id, string token)
        {
            return string.Format("返回結(jié)果, id:{0}", id);
        }

        /// <summary>
        /// 多個(gè)參數(shù)的GET方式獲取數(shù)據(jù)
        /// </summary>
        /// <param name="id">字符串ID</param>
        /// <param name="name">名稱</param>
        /// <param name="token">接口訪問令牌</param>
        /// <returns>返回字符串值</returns>
        [HttpGet]
        public string TestMulti(string id, string name, string token)
        {
            return string.Format("返回結(jié)果, id:{0} name:{1}", id, name);
        }

        /// <summary>
        /// 參數(shù)測試GET返回自定義實(shí)體類對象
        /// </summary>
        /// <param name="id">字符串ID</param>
        /// <param name="token">接口訪問令牌</param>
        /// <returns>返回自定義實(shí)體類對象</returns>
        [HttpGet]
        public virtual CommonResult TestObject(string id, string token)
        {
            return new CommonResult() { Data1 = id, Success = true };
        }

        /// <summary>
        /// 測試GET返回列表對象
        /// </summary>
        /// <param name="token">接口訪問令牌</param>
        /// <returns>返回列表對象</returns>
        [HttpGet]
        public List<string> TestAction(string token)
        {
            List<string> list = new List<string>() { "123", "234", "345" };
            return list;
        }

2)POST方式

POST方式漓帚,同樣也和GET方式的一樣,接口參數(shù)包括有零或一個(gè)參數(shù)午磁,以及多個(gè)參數(shù)的方式尝抖,返回的值可以是簡單的字符串等基礎(chǔ)類型,也可以是復(fù)雜的自定義對象類型等迅皇,這就是幾種常規(guī)的接口處理昧辽。但是,對于多個(gè)參數(shù)的接口定義登颓,我們需要對它們進(jìn)行轉(zhuǎn)換處理搅荞,需要使用JObject param的方式進(jìn)行定義,這樣可以很好對多個(gè)參數(shù)或者自定義的實(shí)體類參數(shù)進(jìn)行解析框咙。

下面是幾種常規(guī)的POST接口定義方式咕痛。

        /// <summary>
        /// 測試使用POST方式提交數(shù)據(jù),參數(shù)輸入為多個(gè)喇嘱,使用JObject處理
        /// </summary>
        /// <returns>返回字符串</returns>
        [HttpPost]
        public string TestPost(JObject param, string token)
        {
            dynamic obj = param;
            string id = obj.id;
            if (obj != null)
            {
                return string.Format("返回結(jié)果, id:{0}", id);
            }
            else
            {
                throw new MyApiException("傳遞參數(shù)出現(xiàn)錯(cuò)誤");
            }
        }

        /// <summary>
        /// 測試使用POST方式提交數(shù)據(jù)茉贡,參數(shù)輸入為多個(gè),使用JObject處理
        /// </summary>
        /// <returns>返回參數(shù)計(jì)算數(shù)值</returns>
        [HttpPost]
        public int TestPostSimple(JObject param)
        {
            dynamic obj = param;
            if (obj != null)
            {
                return obj.x * obj.y * 10;
            }
            else
            {
                throw new MyApiException("傳遞參數(shù)出現(xiàn)錯(cuò)誤");
            }
        }    
        
        /// <summary>
        /// 測試POST的方法者铜,方法統(tǒng)一采用JObject param 方式定義腔丧,包含一個(gè)msg字符串對象构蹬,以及一個(gè)CListItem對象
        /// </summary>
        /// <returns>返回一個(gè)通用的CommonResult對象,包括Data1,Data2,Data3的信息</returns>
        [HttpPost]
        public CommonResult TestPostObject(JObject param)
        {
            dynamic obj = param;
            if (obj != null)
            {
                string msg = obj.msg; //消息對象
                //如果obj.item為類對象悔据,那么需要轉(zhuǎn)換為JObject然后使用ToObject轉(zhuǎn)換為對應(yīng)類型
                CListItem item = ((JObject)obj.item).ToObject<CListItem>();

                var result = new CommonResult(true, msg);
                result.Data1 = msg;
                result.Data2 = item.Text;
                result.Data3 = item.Value;
                return result;
            }
            else
            {
                throw new MyApiException("傳遞參數(shù)出現(xiàn)錯(cuò)誤");
            }
        }
        /// <summary>
        /// 修改分組,方法統(tǒng)一采用JObject param 方式定義俗壹,包括一個(gè)字符串對象contactId科汗,一個(gè)字符串列表對象groupIdList
        /// </summary>
        /// <returns>返回一個(gè)通用的對象</returns>
        [HttpPost]
        public CommonResult TestPostList(JObject param)
        {
            dynamic obj = param;
            if (obj != null)
            {
                string contactId = obj.contactId; //聯(lián)系人ID
                //如果是List<string>的類似列表,不能直接轉(zhuǎn)換绷雏,先轉(zhuǎn)換為JArray后使用ToObject轉(zhuǎn)換為對應(yīng)列表
                List<string> groupIdList = ((JArray)obj.groupIdList).ToObject<List<string>>();

                var result = true; //BLLFactory<Address>.Instance.ModifyAddressGroup(contactId, groupIdList);
                return new CommonResult(result);
            }
            else
            {
                throw new MyApiException("傳遞參數(shù)出現(xiàn)錯(cuò)誤头滔,請檢查是否包含了contactId和groupIdList");
            }
        }

接口類,我們一般把類繼承自自己的API接口基類涎显,并對它的異常處理進(jìn)行處理坤检,以便對錯(cuò)誤統(tǒng)一格式回應(yīng),如下接口類的代碼定義所示期吓。

    /// <summary>
    /// 此控制器用來詳細(xì)介紹各種GET/POST的接口設(shè)計(jì)
    /// 對于GET方式早歇,方法可以接受多個(gè)參數(shù)
    /// 對于POST方式,方法如果有參數(shù)使用POST方式讨勤,統(tǒng)一采用JObject param對象參數(shù)箭跳。
    /// 如果POST方式有多個(gè)參數(shù),如Web API接口加token潭千,則需要客戶端把該參數(shù)追加在URL上谱姓,如url?token=123,然后在使用POST操作
    /// </summary>
    [ExceptionHandling]
    public class TestController : BaseApiController

其中ExceptionHandling是我們的統(tǒng)一異常過濾處理定義刨晴,代碼如下所示屉来。

    /// <summary>
    /// API自定義錯(cuò)誤過濾器屬性
    /// </summary>
    public class ExceptionHandlingAttribute : ExceptionFilterAttribute
    {
        /// <summary>
        /// 統(tǒng)一對調(diào)用異常信息進(jìn)行處理,返回自定義的異常信息
        /// </summary>
        /// <param name="context">HTTP上下文對象</param>
        public override void OnException(HttpActionExecutedContext context)
        {
            //自定義異常的處理
            MyApiException ex = context.Exception as MyApiException;
            if (ex != null)
            {
                //記錄關(guān)鍵的異常信息
                LogHelper.Error(context.Exception);

                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
                {
                    //封裝處理異常信息狈癞,返回指定JSON對象
                    Content = new StringContent(new BaseResultJson(ex.Message, false, ex.errcode).ToJson()),
                    ReasonPhrase = "Exception"
                });
            }            
            
            //常規(guī)異常的處理
            string msg = string.IsNullOrEmpty(context.Exception.Message) ? "接口出現(xiàn)了錯(cuò)誤茄靠,請重試或者聯(lián)系管理員" : context.Exception.Message;
            throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
            {
                Content = new StringContent(msg),
                ReasonPhrase = "Critical Exception"
            });
        }
    }

3)小程序端代碼處理

小程序端主要是通過JS代碼進(jìn)行處理,實(shí)現(xiàn)數(shù)據(jù)的獲取及提交處理等亿驾。

如我們列舉一個(gè)代表性的POST處理代碼嘹黔,如下所示。

  //測試POst方法
  wx.request({
    url: 'http://localhost:27206/api/SmallApp/Test/TestPostObject',
    data: { 
      msg : '測試內(nèi)容', 
      item: {Text :'Text', Value:'testValue'}
    },
    header: {'Content-Type': 'application/json' },
    method: 'POST',
    success: function (res) {
      console.log(res.data);
    }
  });

而對于GET方式莫瞬,我們的小程序調(diào)用方式如下所示儡蔓。

  getFilms: function(start) {
    console.log('start:' + start);
    var that = this

    wx.request({
      url: 'http://www.iqidi.com/api/h5/test/movies',
      data: {
        offset: start,
        type: 'hot',
        limit: that.data.limit
      },
      header: {
          'Content-Type': 'application/json'
      },
      success: function (res) {
        console.log(res.data)

        var data = res.data.data;
        console.log(data);
        if (data.movies.length === 0) {
          that.setData({
            hasMore: false,
            hideLoading :true,
          })
        } 
        else {
          that.setData({
            films: that.data.films.concat(data.movies),
            start: that.data.start + data.movies.length,
            hasMore: true,
            hideLoading :true,
          });
        }
      }
    })

以上就是我們常規(guī)接口(單個(gè)參數(shù)或者多個(gè)參數(shù),簡單對象和復(fù)雜對象的處理)的定義代碼疼邀,希望讀者在開發(fā)Web API接口的時(shí)候喂江,可以有所幫助。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末旁振,一起剝皮案震驚了整個(gè)濱河市获询,隨后出現(xiàn)的幾起案子涨岁,更是在濱河造成了極大的恐慌,老刑警劉巖吉嚣,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梢薪,死亡現(xiàn)場離奇詭異,居然都是意外死亡尝哆,警方通過查閱死者的電腦和手機(jī)秉撇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秋泄,“玉大人琐馆,你說我怎么就攤上這事『阈颍” “怎么了瘦麸?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長歧胁。 經(jīng)常有香客問我滋饲,道長,這世上最難降的妖魔是什么与帆? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任了赌,我火速辦了婚禮,結(jié)果婚禮上玄糟,老公的妹妹穿的比我還像新娘勿她。我一直安慰自己,他們只是感情好阵翎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布逢并。 她就那樣靜靜地躺著,像睡著了一般郭卫。 火紅的嫁衣襯著肌膚如雪砍聊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天贰军,我揣著相機(jī)與錄音玻蝌,去河邊找鬼。 笑死词疼,一個(gè)胖子當(dāng)著我的面吹牛俯树,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播贰盗,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼许饿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了舵盈?” 一聲冷哼從身側(cè)響起陋率,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤球化,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后瓦糟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體筒愚,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年菩浙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锨能。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡芍耘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出熄阻,到底是詐尸還是另有隱情斋竞,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布秃殉,位于F島的核電站坝初,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏钾军。R本人自食惡果不足惜鳄袍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吏恭。 院中可真熱鬧拗小,春花似錦、人聲如沸樱哼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽搅幅。三九已至阅束,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茄唐,已是汗流浹背息裸。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沪编,地道東北人呼盆。 一個(gè)月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像漾抬,于是被迫代替她去往敵國和親宿亡。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容