微信小程序給咱們提供了一個很好的開發平臺,能夠用於展示各類數據和實現豐富的功能,經過小程序的請求Web API 平臺獲取JSON數據後,能夠在小程序界面上進行數據的動態展現。在數據的關鍵 一環中,咱們設計和編寫Web API平臺是很是重要的,經過這個咱們能夠實現數據的集中控制和管理,本篇隨筆介紹基於Asp.NET MVC的Web API接口層的設計和常見接口代碼的展現,以便展現咱們常規Web API接口層的接口代碼設計、參數的處理等內容。html
咱們總體性的架構設計,包含一個Web管理後臺、一個Web API統一接口層、固然還有數據庫什麼,另外還有一個小程序客戶端。整個架構體系仍是以我以前隨筆介紹的《整合微信小程序的Web API接口層的架構設計》內容爲藍本數據庫
整個體系以Web API爲主提供服務,同時後臺管理系統經過各類界面維護着數據的增刪改等基礎管理工做。json
Web API的分層,咱們能夠經過下圖來了解具體的分層結構。小程序
隨着基於JSON格式的Web API的普遍應用,愈來愈多的企業採用Web API接口服務層,做爲統一接口的核心所在,也成爲Web API核心層。基於JSON格式的接口,能夠普遍地、跨平臺的應用於IOS、安卓等移動端,也能夠應用在常規的Web業務系統,Winform業務系統、微信應用、微信小程序等方方面面,所以企業內部造成本身是的一套Web API標準和詳細的文檔很是重要。微信小程序
咱們能夠細化爲下面的架構設計圖,全部模塊均圍繞着Web API 接口層進行擴展,底層的數據存儲對上層的應用是徹底透明,咱們能夠根據須要拆分各類業務數據庫,以及使用咱們認爲合適的數據庫。api
其中咱們在Web API接口層上還看到一個微信消息交互的模塊,這個模塊咱們爲了方便域名端口的處理,和Web API 是統一放在一塊兒的,它負責和騰訊微信服務器進行消息的交互處理,從而實現各類消息推送處理。服務器
GET方式,接口參數包括有零或一個參數,以及多個參數的方式,返回的值能夠是簡單的字符串等基礎類型,也能夠是複雜的自定義對象類型等,以下面幾種接口代碼所示。微信
/// <summary> /// 簡單的GET方式獲取數據 /// </summary> /// <param name="id">字符串ID</param> /// <param name="token">接口訪問令牌</param> /// <returns>返回字符串值</returns> [HttpGet] public string Test(string id, string token) { return string.Format("返回結果, id:{0}", id); } /// <summary> /// 多個參數的GET方式獲取數據 /// </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("返回結果, id:{0} name:{1}", id, name); } /// <summary> /// 參數測試GET返回自定義實體類對象 /// </summary> /// <param name="id">字符串ID</param> /// <param name="token">接口訪問令牌</param> /// <returns>返回自定義實體類對象</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; }
POST方式,一樣也和GET方式的同樣,接口參數包括有零或一個參數,以及多個參數的方式,返回的值能夠是簡單的字符串等基礎類型,也能夠是複雜的自定義對象類型等,這就是幾種常規的接口處理。可是,對於多個參數的接口定義,咱們須要對它們進行轉換處理,須要使用JObject param的方式進行定義,這樣能夠很好對多個參數或者自定義的實體類參數進行解析。架構
下面是幾種常規的POST接口定義方式。app
/// <summary> /// 測試使用POST方式提交數據,參數輸入爲多個,使用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("返回結果, id:{0}", id); } else { throw new MyApiException("傳遞參數出現錯誤"); } } /// <summary> /// 測試使用POST方式提交數據,參數輸入爲多個,使用JObject處理 /// </summary> /// <returns>返回參數計算數值</returns> [HttpPost] public int TestPostSimple(JObject param) { dynamic obj = param; if (obj != null) { return obj.x * obj.y * 10; } else { throw new MyApiException("傳遞參數出現錯誤"); } } /// <summary> /// 測試POST的方法,方法統一採用JObject param 方式定義,包含一個msg字符串對象,以及一個CListItem對象 /// </summary> /// <returns>返回一個通用的CommonResult對象,包括Data1,Data2,Data3的信息</returns> [HttpPost] public CommonResult TestPostObject(JObject param) { dynamic obj = param; if (obj != null) { string msg = obj.msg; //消息對象 //若是obj.item爲類對象,那麼須要轉換爲JObject而後使用ToObject轉換爲對應類型 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("傳遞參數出現錯誤"); } } /// <summary> /// 修改分組,方法統一採用JObject param 方式定義,包括一個字符串對象contactId,一個字符串列表對象groupIdList /// </summary> /// <returns>返回一個通用的對象</returns> [HttpPost] public CommonResult TestPostList(JObject param) { dynamic obj = param; if (obj != null) { string contactId = obj.contactId; //聯繫人ID //若是是List<string>的相似列表,不能直接轉換,先轉換爲JArray後使用ToObject轉換爲對應列表 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("傳遞參數出現錯誤,請檢查是否包含了contactId和groupIdList"); } }
接口類,咱們通常把類繼承自本身的API接口基類,並對它的異常處理進行處理,以便對錯誤統一格式迴應,以下接口類的代碼定義所示。
/// <summary> /// 此控制器用來詳細介紹各類GET/POST的接口設計 /// 對於GET方式,方法能夠接受多個參數 /// 對於POST方式,方法若是有參數使用POST方式,統一採用JObject param對象參數。 /// 若是POST方式有多個參數,如Web API接口加token,則須要客戶端把該參數追加在URL上,如url?token=123,而後在使用POST操做 /// </summary> [ExceptionHandling] public class TestController : BaseApiController
其中ExceptionHandling是咱們的統一異常過濾處理定義,代碼以下所示。
/// <summary> /// API自定義錯誤過濾器屬性 /// </summary> public class ExceptionHandlingAttribute : ExceptionFilterAttribute { /// <summary> /// 統一對調用異常信息進行處理,返回自定義的異常信息 /// </summary> /// <param name="context">HTTP上下文對象</param> public override void OnException(HttpActionExecutedContext context) { //自定義異常的處理 MyApiException ex = context.Exception as MyApiException; if (ex != null) { //記錄關鍵的異常信息 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" }); } //常規異常的處理 string msg = string.IsNullOrEmpty(context.Exception.Message) ? "接口出現了錯誤,請重試或者聯繫管理員" : context.Exception.Message; throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError) { Content = new StringContent(msg), ReasonPhrase = "Critical Exception" }); } }
小程序端主要是經過JS代碼進行處理,實現數據的獲取及提交處理等。
如咱們列舉一個表明性的POST處理代碼,以下所示。
//測試POst方法 wx.request({ url: 'http://localhost:27206/api/SmallApp/Test/TestPostObject', data: { msg : '測試內容', item: {Text :'Text', Value:'testValue'} }, header: {'Content-Type': 'application/json' }, method: 'POST', success: function (res) { console.log(res.data); } });
而對於GET方式,咱們的小程序調用方式以下所示。
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, }); } } })
以上就是咱們常規接口(單個參數或者多個參數,簡單對象和複雜對象的處理)的定義代碼,但願讀者在開發Web API接口的時候,能夠有所幫助。