封裝微軟牛津計劃API用戶端
牛津計劃的API是由一個基礎Url、服務名稱、參數組成為的服務,大多是POST(我還沒有完全看完),這些參數多是字串,但也有流格式(比如上傳圖片什麼的),我們的ProjecToxfordClientHelper就是計劃將牛津API的實現進行封裝,為我們不同的APIController提供服務。
我們先定義一些基本的欄位
private const string serviceHost = "https://api.projectoxford.ai/face/v1.0";private const string KEY = "";private HttpClient client;private static string photofolder = System.Configuration.ConfigurationManager.AppSettings["ProjecToxfordPhotos"];
serviceHost就是牛津的API,KEY你可以通過註冊牛津開發計劃來獲得,photofolder是保持我們需要上傳圖所在的位置。
我們在建構函式中初始化HttpClient,為HttpClient添加兩個必須的頭標識。
public ProjecToxfordClientHelper(){ client = new HttpClient(); var queryString = HttpUtility.ParseQueryString(string.Empty); client.DefaultRequestHeaders.Add("ContentType", "application/json"); client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", KEY);}
接下來,我們要實現兩種POST的提交,一種是提交流參數,一種是提交字串參數
實現提交字串參數的POST
public async Task<ProjecToxfordResponseModels> PostAsync(string querkey, object body, Dictionary<string, string> querystr = null){ var queryString = HttpUtility.ParseQueryString(string.Empty); if (querystr != null) { foreach (var entry in querystr) { queryString[entry.Key] = entry.Value; } } var uri = string.Format("{0}/{1}?{2}", serviceHost, querkey, queryString); var jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(body); byte[] byteData = Encoding.UTF8.GetBytes(jsonStr); HttpResponseMessage response; using (var content = new ByteArrayContent(byteData)) { content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); response = await client.PostAsync(uri, content); var msg = await response.Content.ReadAsStringAsync(); return new ProjecToxfordResponseModels(msg, response.StatusCode); }}
所謂的字串參數就是將實現Fields的對象以JSON格式序列化,然後POST給牛津API。
var jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(body);byte[] byteData = Encoding.UTF8.GetBytes(jsonStr);
所以要記得content的內容類型要定義為
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
那類似圖片這些流檔案不能採用這個方法,所以我們重載了一個方法
public async Task<ProjecToxfordResponseModels> PostAsync(string querkey, byte[] body, Dictionary<string, string> querystr = null){ var queryString = HttpUtility.ParseQueryString(string.Empty); if (querystr != null) { foreach (var entry in querystr) { queryString[entry.Key] = entry.Value; } } var uri = string.Format("{0}/{1}?{2}", serviceHost, querkey, queryString); HttpResponseMessage response; using (var content = new ByteArrayContent(body)) { content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); response = await client.PostAsync(uri, content); var msg = await response.Content.ReadAsStringAsync(); return new ProjecToxfordResponseModels(msg, response.StatusCode); }}
看下參數,流格式的內容需要以Byte數組的方式進行傳遞,但實際的處理中沒有什麼太大的不同,如果傳遞的是Byte數組就直接處理,否則先序列化為Byte數組,但是要注意的是,流媒體的json的編碼是不同的, Created with Raphaël 2.1.0 開始 is byte array? byetArray To Content is byte array? application/octet-stream End application/json JSON SerialzeObj getBytes yes no yes no
我們再提供一個協助處理牛津API傳回值的方法
public HttpResponseMessage CreateHttpResponseMessage(HttpRequestMessage request, ProjecToxfordResponseModels result){ if (result.StatusCode == HttpStatusCode.OK) { return request.CreateResponse(HttpStatusCode.OK, result.Message); } else { return request.CreateErrorResponse(result.StatusCode, result.Message); }}