2013-06-05 57 views
1

所以我試圖把一些非常簡單而優雅的代碼樣本,共同幫助人們使用我的API。我正在處理的最新語言是C#。C#應用程序/ X WWW的形式,進行了urlencoded的OAuth和HTTP REST請求HttpClient的

我認爲IETF OAuth2.0的標準I讀意味着在HTTP請求的內容類型必須是「應用程序/ x WWW的形式進行了urlencoded」。我擁有的Django API服務器目前似乎只支持這種Content-Type(用於OAuth資源)。其他語言POST內容默認爲這種方式!

經過廣泛的研究和幾個實驗後,我想知道如果我錯過了一些基本的東西。當然會有一個有用的庫OR技術來創建... urlencoded字符串或至少有其他人必須碰到這個?

我會概述一下迄今爲止我所見過的最好的解決方案,但它似乎是錯誤的。

也從一堆的互聯網瀏覽我想我會使用HttpClient庫。我喜歡它使用異步模型的事實,對於使用WPF或XAML或Windows 8應用程序的任何開發人員來說,這可能會更有用。它也適用於控制檯和表單。

我使用Newtonsoft Json.Net庫進行序列化。首先我創建一個授權字符串的POCO。然後我將它序列化到JSON,然後到鍵/值對,然後遍歷所需的'='和'&'字符串連接的鍵/值對,然後UTF-8,然後轉義空格等。

//Setup HTTP request 
HttpClient httpRequest = new HttpClient(); 
httpRequest.DefaultRequestHeaders.Add("Accept", "application/json"); 
string urlBase = "https://__secret__/api/v1/"; 
HttpResponseMessage msg = new HttpResponseMessage(); 

//POST to oauth to get token (must be sent as "application/x-www-form-urlencoded") 
OAuthConfig oAuthCredentials = new OAuthConfig { client_id = client_id, client_secret = secret, username = "__secret__", password = "__secret__", grant_type = "__secret__" }; 
string jsonString = JsonConvert.SerializeObject(oAuthCredentials); //convert to JSON 
Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonString); //convert to key/value pairs 
string urlEncodedData = ConvertToFormUrlEncodedFormat(values); 
HttpContent payload = new StringContent(urlEncodedData, Encoding.UTF8, "application/x-www-form-urlencoded"); 
msg = httpRequest.PostAsync(urlBase + "oauth/access_token/", payload).Result; 
string responseBodyAsText = msg.Content.ReadAsStringAsync().Result; 
Console.WriteLine(responseBodyAsText); 

我能想到的是其他選項...

的反思,但是挖掘到了一個代碼示例中的反射似乎有點狂躁。

事實證明,除了OAuth設置,API的其餘部分支持JSON類型的POST。所以我想我可以編寫一個函數來遍歷oAuthConfig模型並鏈接一個字符串,因爲POCO模型不太可能改變,並且是唯一需要urlEncoding的模型,我可以預見。這將使我們免於使用詞典的混亂。字典的使用,然後迭代更通用,但也許有點OTT。

我想大多數時候人們會使用JSON,因此顯示這種情況可能發生的情況是有用的。

總體看來挺難的序列化POCO模型爲一個字符串和/或一個url編碼字符串。

問題

  • 沒有OAuth的任務url編碼,你能不能轉換服務器端?
  • 是HttpClient的最佳選擇,是否異步?
  • 有沒有更簡單的方法來序列化一個POCO ... form-urlencoded?

感謝您的任何有用的意見。

回答

0
//I disclaimer everything and note that I haven't re-checked if this posted code works. 

using System; 
using System.Text; 
using System.Collections.Generic; 
using Newtonsoft.Json; //install with Nuget package installer- "json.Net" 
using System.Net.Http; //install with Nuget package installer- "...Web API client libraries" 
using System.Net; 
using System.IO; 
using System.Runtime.Serialization.Json;  //security risk till certificate fixed 

namespace CSharpDemoCodeConsole 
{ 
    class Program 
    { 
     const string api_key = "your_api_key"; //set your api_key here 
     const string user_auth = "your_username" + ":" + "your_password"; // set your user credentials here 
     const string urlBase = "https://@[email protected]/api/v1"; 

     static void Main(string[] args) 
     { 
      Console.WriteLine("Making call to webserver asynchronously"); 
      MakeCallAsynchronously(); 
      Console.WriteLine("**************************************"); 

      Console.WriteLine("Making call to webserver synchronously"); 
      MakeCallSynchronously(); 
      Console.WriteLine("**************************************"); 

      Console.WriteLine("Making call to webserver synchronously without Newtonsoft serialization"); 
      MakeCallSynchronouslyWithoutNewtonSoft(); 
      Console.WriteLine("Press spacebar to close the application"); 
      Console.ReadKey(); 
     } 

     private static void MakeCallAsynchronously() 
     { 
      //Always accept untrusted certificates - don't use in production 
      ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 

      //Setup request 
      string authorizeString = Convert.ToBase64String(Encoding.ASCII.GetBytes(user_auth)); 
      HttpClient httpRequest = new HttpClient(); 
      httpRequest.DefaultRequestHeaders.Add("Authorization", "Basic " + authorizeString); 
      httpRequest.DefaultRequestHeaders.Add("Accept", "application/json"); 

      //GET from places resource 
      try 
      { 
       var requestTask = httpRequest.GetAsync(urlBase + "places/" + "?api_key=" + api_key, 
       System.Net.Http.HttpCompletionOption.ResponseContentRead); 

       //Update UI while waiting for task to complete 
       while (requestTask.Status != System.Threading.Tasks.TaskStatus.RanToCompletion) 
       { 
        Console.Write("."); 
        System.Threading.Thread.Sleep(30); 
       } 
       if (requestTask.Result.StatusCode != HttpStatusCode.OK) 
       { 
        Console.WriteLine("Unexpected response from server: {0}", requestTask.Result); 
        return; 
       } 
       var places = JsonConvert.DeserializeObject<Page<Place>>(requestTask.Result.Content.ReadAsStringAsync().Result); 
       Console.WriteLine("GET places response " + requestTask.Result.Content.ReadAsStringAsync().Result); 
      } 
      catch (WebException ex) 
      { 
       Console.WriteLine(ex.ToString()); 
       return; 
      } 

      //POST to places resource 
      try 
      { 
       string jsonString = JsonConvert.SerializeObject(new Place { name = "test place", latitude = 0, longitude = 0 }); 
       HttpContent payload = new StringContent(jsonString, Encoding.UTF8, "application/json"); 
       var requestTask = httpRequest.PostAsync(urlBase + "places/" + "?api_key=" + api_key, payload); 

       //Update UI while waiting for task to complete 
       while (requestTask.Status != System.Threading.Tasks.TaskStatus.RanToCompletion) 
       { 
        Console.Write("."); 
        System.Threading.Thread.Sleep(30); 
       } 
       if (requestTask.Result.StatusCode != HttpStatusCode.Created) 
       { 
        Console.WriteLine("Unexpected response from server: {0}", requestTask.Result); 
        return; 
       } 
       Console.WriteLine("POST places response " + requestTask.Result.Content.ReadAsStringAsync().Result); 
      } 
      catch (WebException ex) 
      { 
       Console.WriteLine(ex.ToString()); 
       return; 
      } 
     } 

     private static void MakeCallSynchronously() 
     { 
      //Always accept untrusted certificates - don't use in production 
      ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 

      //Setup Request 
      string authorizeString = Convert.ToBase64String(Encoding.ASCII.GetBytes(user_auth)); 
      var client = new WebClient(); 
      client.Headers.Add("Authorization", "Basic " + authorizeString); 
      client.Headers.Add("Accept", "application/json"); 

      //GET from places resource 
      try 
      { 
       var responseStream = client.OpenRead(urlBase + "places/" + "?api_key=" + api_key); 
       var response = (new StreamReader(responseStream).ReadToEnd()); 
       var places = JsonConvert.DeserializeObject<Page<Place>>(response); 
       Console.WriteLine("GET places response " + response); 
      } 
      catch (WebException ex) 
      { 
       Console.WriteLine(ex.ToString()); 
      } 

      //POST to places resource 
      try 
      { 
       client.Headers.Add("Accept", "application/json"); 
       client.Headers.Add("Content-Type", "application/json"); 
       string jsonString = JsonConvert.SerializeObject(new Place { name = "test place", latitude = 0, longitude = 0 }); 
       client.Encoding = System.Text.Encoding.UTF8; 
       string response = client.UploadString(urlBase + "places/" + "?api_key=" + api_key, jsonString); 
       Console.WriteLine("POST places response " + response); 
      } 
      catch (WebException ex) 
      { 
       Console.WriteLine(ex.ToString()); 
       return; 
      } 
     } 

     private static void MakeCallSynchronouslyWithoutNewtonSoft() 
     { 
      //Always accept untrusted certificates - don't use in production 
      ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 

      //Setup Request 
      string authorizeString = Convert.ToBase64String(Encoding.ASCII.GetBytes(user_auth)); 
      var client = new WebClient(); 
      client.Headers.Add("Authorization", "Basic " + authorizeString); 
      client.Headers.Add("Accept", "application/json"); 

      //GET from places resource 
      try 
      { 
       var responseStream = client.OpenRead(urlBase + "places/" + "?api_key=" + api_key); 
       MemoryStream ms = new MemoryStream(); 
       responseStream.CopyTo(ms); 
       ms.Position = 0; 
       var placesDeserializer = new DataContractJsonSerializer(typeof(Page<Place>)); 
       var places = (Page<Place>)placesDeserializer.ReadObject(ms); 
       ms.Position = 0; 
       string response = (new StreamReader(ms).ReadToEnd()); 
       ms.Close(); 
       Console.WriteLine("GET places response " + response); 
      } 
      catch (WebException ex) 
      { 
       Console.WriteLine(ex.ToString()); 
       return; 
      } 

      //POST to places resource 
      try 
      { 
       client.Headers.Add("Accept", "application/json"); 
       client.Headers.Add("Content-Type", "application/json"); 
       DataContractJsonSerializer placesSerializer = new DataContractJsonSerializer(typeof(Place)); 
       Place place = new Place { name = "test place", latitude = 0, longitude = 0 }; 
       MemoryStream ms = new MemoryStream(); 
       placesSerializer.WriteObject(ms, place); 
       byte[] json = ms.ToArray(); 
       ms.Close(); 
       string jsonString = Encoding.UTF8.GetString(json, 0, json.Length); 
       client.Encoding = System.Text.Encoding.UTF8; 
       string response = client.UploadString(urlBase + "places/" + "?api_key=" + api_key, jsonString); 
       Console.WriteLine("POST places response " + response); 

      } 
      catch (WebException ex) 
      { 
       Console.WriteLine(ex.ToString()); 
       return; 
      } 
     } 
    } 

    public class Place 
    { 
     [JsonProperty("url")] 
     public string url { get; set; } 
     [JsonProperty("name")] 
     public string name { get; set; } 
     [JsonProperty("latitude")] 
     public float latitude { get; set; } 
     [JsonProperty("longitude")] 
     public float longitude { get; set; } 
    } 

    public class Page<T> 
    { 
     [JsonProperty("count")] 
     public int count { get; set; } 
     [JsonProperty("next")] 
     public string next { get; set; } 
     [JsonProperty("previous")] 
     public string previous { get; set; } 
     [JsonProperty("results")] 
     public List<T> results { get; set; } 
    } 
} 
1
var model = new LoginModel { Username = "[email protected]", Password = "123456", DeviceId = "123456789", RoleId = 1 }; 
      url.Append("/Login"); 
      string data = JsonConvert.SerializeObject(model);// "{\"username\":\"[email protected]\",\"password\":\"vipin123\"}"; 
      NameValueCollection inputs = new NameValueCollection(); 
      inputs.Add("json", data); 
      WebClient client = new WebClient(); 
      var reply = client.UploadValues(url.ToString(), inputs); 
      string temp = Encoding.ASCII.GetString(reply); 
      var result = JsonConvert.DeserializeObject<MessageTemplateModel> 
(temp); 

API調用

public async Task<IHttpActionResult> Login(HttpRequestMessage request)//(LoginModel modelN) 
     { 
      try 
      { 
       var form = request.Content.ReadAsFormDataAsync().Result; 
       var modelN = JsonConvert.DeserializeObject<LoginModel>(form["json"].ToString()); 
       // token = JsonConvert.DeserializeObject<string>(form["token"].ToString()); 
       bool istoken = _appdevice.GettokenID(modelN.DeviceId); 
       if (!istoken) 
       { 
        statuscode = 0; 
        message = ErrorMessage.TockenNotvalid; 
        goto invalidtoken; 
       } 
       User model = new User(); 
       // var session = HttpContext.Current.Session; 
       // session.Add("UserRole", GetProfileId.UserRole); 
       var user = await _userManager.FindAsync(modelN.Username, modelN.Password);}} 

我能夠調用從設備和網絡應用的URL編碼器請求。

相關問題