C# RESTful API 訪問輔助類

REST 全稱是 Representational State Transfer,有人說它是一種風格,並不是一種標準,我的以爲挺有道理。它自己並無創造新的技術、組件與服務,更像是告訴你們如何更好地使用現有Web標準中的一些準則和約束,也不能否認,RESTFul 是目前最流行的 API 設計規範,用於 Web 數據接口的設計。git

RESTful 風格的 API,在 HTTP 協議上使用的是標準 HTTP 方法,GET、PUT、POST 和 DELETE 等。github

經常使用實踐

(1)API 返回結果一般爲 JSON 形式,請求的頭部屬性 Accept 一般設置爲 application/jsonweb

(2)請求的 Body 數據部分使用 JSON 形式json

(3)鑑權信息使用 JWT 等形式的受權碼方式,放在請求頭部屬性中傳輸,屬性名稱自定義,如 auth,token 等等api

輔助類設計

(1)屬性定義app

定義屬性:TokenHeaderNameurl

上述實踐描述中,自定義部分爲鑑權信息在頭部屬性中的名稱,定義該屬性表示這個名稱。設計

定義屬性:DefaultTokencode

考慮到鑑權信息在某些場景下可初始爲一個固定值,定義該屬性在默認狀況下使用。orm

具體定義以下:

// 鑑權 token 的請求頭屬性名稱
public String TokenHeaderName { get; set; }

// 默認的鑑權 token 信息
public String DefaultToken { get; set; }

(2)方法定義

方法定義跟標準的 HTTP 方法一致,這裏定義經常使用的 Get、Put、Post、Delete 方法。

再抽取其中會重複的部分造成一些私有方法來複用,再重載一些方法使得能夠應用默認參數值。

(2.1)構造方法

構造時能夠指定鑑權頭部屬性名和 token,也能夠不指定。

public RestApiVisitHelper()
{

}

// 構造時設置鑑權 token 的請求頭屬性名稱
public RestApiVisitHelper(String tokenHeaderName)
{
    TokenHeaderName = tokenHeaderName;
}

// 構造時設置鑑權 token 的請求頭屬性名稱,以及默認的 token 值
public RestApiVisitHelper(String tokenHeaderName, String defaultToken){
    TokenHeaderName = tokenHeaderName;
    DefaultToken = defaultToken;
}

(2.2)訪問所需輔助方法

(2.2.1) 建立 WebClient,設置好相關屬性,包括鑑權頭部信息

// 建立 WebClient 並設置好 token 信息
private WebClient CreateWebClient(String token)
{
    System.Net.ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true);
    System.Net.WebClient webClientObj = new System.Net.WebClient();
    webClientObj.Headers.Add("Accept", "application/json");
    if (!String.IsNullOrEmpty(TokenHeaderName) && !String.IsNullOrEmpty(token))
    {
        webClientObj.Headers.Add(TokenHeaderName, token);
    }
    webClientObj.Encoding = Encoding.UTF8;
    return webClientObj;
}

(2.2.2)將查詢參數格式化拼接成最終 url

// 將查詢參數格式化拼接到 url 上造成最終的訪問地址
private String FormatUrl(String apiUrl, Hashtable queryParams)
{
    String queryString = "";
    foreach (var k in queryParams.Keys)
    {
        if (!String.IsNullOrEmpty(queryString))
        {
            queryString += "&";
        }
        queryString += String.Format("{0}={1}", k, queryParams[k]);
    }
    if (!String.IsNullOrEmpty(queryString))
    {
        apiUrl += "?" + queryString;
    }
    return apiUrl;
}

(2.2.3)異常統一處理

出現請求異常時,能夠統一進行處理,具體返回結果可自行定義。

// 異常時返回的信息:應該根據實際須要進行返回
private String WhenError(Exception e)
{
    JObject result = new JObject();
    result["err_code"] = -1;  
    if (e is WebException)
    {
        var we = (WebException)e;
        if (we.Response != null)  // 若是有輸出則仍然返回實際輸出
        {
            return new StreamReader(we.Response.GetResponseStream()).ReadToEnd();
        }
        else
        {                    
            result["err_msg"] = we.Message;
        }
    }
    else
    { 
        result["err_msg"] = e.Message; 
    }
    return result.ToString(Newtonsoft.Json.Formatting.None);
}

(2.3)公開方法具體實現

有了以上輔助方法,實現代碼會變得簡潔,且各個方法代碼結構相似。如下以 Post 方法(包括重載) 爲例展現基本實現。

/// <summary>
/// Post Api 返回結果文本,使用默認的鑑權 token
/// </summary>
/// <param name="apiUrl"></param>
/// <param name="queryParams"></param>
/// <param name="body"></param>
/// <returns></returns>
public String Post(string apiUrl, Hashtable queryParams, JObject body)
{
    return Post(apiUrl, queryParams, body, DefaultToken);
}

/// <summary>
/// Post Api 返回結果文本
/// </summary>
/// <param name="apiUrl"></param>
/// <param name="queryParams"></param>
/// <param name="body"></param>
/// <param name="token"></param>
/// <returns></returns>
public String Post(string apiUrl, Hashtable queryParams, JObject body, String token)
{
    System.Net.WebClient webClientObj = CreateWebClient(token);

    apiUrl = FormatUrl(apiUrl, queryParams);
    try
    {
        String result = webClientObj.UploadString(apiUrl, "POST", body.ToString(Newtonsoft.Json.Formatting.None));
        return result;
    }
    catch (Exception ce)
    {
        return WhenError(ce);
    }
}

完整源碼

https://github.com/triplestudio/helloworld/blob/master/RestApiVisitHelper.cs

相關文章
相關標籤/搜索