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

相关文章
相关标签/搜索