2015-05-30 28 views
1

我正在用Xamarin和C#進行一些移動開發。我正在爲Android應用程序構建一個簡單的登錄屏幕,我使用HttpClient來進行實際的通話,但我堅持一些細節以使其正常工作。通過使用C#和HttpClient調用REST API來檢索JSON內容

我已經建立了一個簡單的Client類,它代表了我的API客戶端:

using System; 
using System.Net.Http; 
using System.Net.Http.Headers; 
using System.Threading.Tasks; 

namespace Acme.Api 
{ 
    public class Session 
    { 
     public string Token; 
     public int Timeout; 
    } 

    public class Client 
    { 
     public async Task<string> authenticate(string username, string password) 
     { 
      using (var client = new HttpClient()) 
      { 
       string content = null; 

       client.BaseAddress = new Uri ("https://example.com/api/"); 
       client.DefaultRequestHeaders.Accept.Clear(); 
       client.DefaultRequestHeaders.Accept.Add (new MediaTypeWithQualityHeaderValue ("application/json")); 
       client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue ("Basic", string.Format ("{0}:{1}", username, password)); 

       HttpResponseMessage response = await client.PostAsync ("auth", null); 

       content = await response.Content.ReadAsStringAsync(); 

       return content; 
      } 
     } 
    } 
} 

正如你所看到的,authenticate方法使用POST在服務器上創建一個新的會話。 /auth端點返回帶有令牌和超時值的JSON blob。

這是怎麼authenticate方法被稱爲:

Client myClient = new Client(); 

Task<string> contentTask = myClient.authenticate(username, password); 

var content = contentTask.ToString(); 

Console.Out.WriteLine(content); 

content從不輸出任何東西。我顯然(毫無疑問)在做各種不對的事情。

我該如何讓我的authenticate方法返回JSON字符串我期望的?

我一直在使用這些來源中尋找靈感:

http://developer.xamarin.com/guides/cross-platform/advanced/async_support_overview/ http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client

回答

0

身份驗證()是一個異步方法,所以你需要等待它

string content = await myClient.authenticate(username, password); 
+0

是不是'await'已經在'authenticate'方法內部使用過了嗎?另外,將'await'放在'authenticate'方法的前面似乎是Xamarin IDE中的語法錯誤(錯誤出現在我似乎無法複製的工具提示中)。 – Luke

3

既然你返回Task而不僅僅是一個string您需要等待myclient.authenticate方法。

如果你重做了string,你不必等待。我認爲你的情況是可能的,只需將返回類型從Task<string>更改爲string即可。

您克倫特authenticate方法:

public class Client 
    {   
     public async Task<string> authenticate(string username, string password) 
     { 
      using (var client = new HttpClient()) 
      { 
       string content = null; 

       client.BaseAddress = new Uri ("https://example.com/api/"); 
       client.DefaultRequestHeaders.Accept.Clear(); 
       client.DefaultRequestHeaders.Accept.Add (new MediaTypeWithQualityHeaderValue ("application/json")); 
       client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue ("Basic", string.Format ("{0}:{1}", username, password)); 

       HttpResponseMessage response = await client.PostAsync ("auth", null); 
//deserialize json, not sure if you need it as its not an object that you are returning 
       jsonstring = await response.Content.ReadAsStringAsync(); 
var content = JsonConvert.DeserializeObject<string>(jsonstring); 
       return content; 
      } 
     } 
    } 

消費客戶爲:

async void btn_click(string username,string password) 
{ 
    // This should be an async method as well 
    Client myClient = new Client(); 
    // added await 
    string content = await myClient.authenticate(username, password); 
    Console.Out.WriteLine(content); 
} 

的示例代碼中的靈感來源已經存在

GetButton.Click += async (sender, e) => { 

    Task<int> sizeTask = DownloadHomepage(); 

    ResultTextView.Text = "loading..."; 
    ResultEditText.Text = "loading...\n"; 

    // await! control returns to the caller 
    // "See await" 
    var intResult = await sizeTask 

    // when the Task<int> returns, the value is available and we can display on the UI 
    ResultTextView.Text = "Length: " + intResult ; 
    // "returns" void, since it's an event handler 
}; 

public async Task<int> DownloadHomepage() 
{ 
    var httpClient = new HttpClient(); // Xamarin supports HttpClient! 

    Task<string> contentsTask = httpClient.GetStringAsync("http://xamarin.com"); // async method! 

    // await! control returns to the caller and the task continues to run on another thread 
    // "See await" 
    string contents = await contentsTask; 

    ResultEditText.Text += "DownloadHomepage method continues after async call. . . . .\n"; 

    // After contentTask completes, you can calculate the length of the string. 
    int exampleInt = contents.Length; 

    ResultEditText.Text += "Downloaded the html and found out the length.\n\n\n"; 

    ResultEditText.Text += contents; // just dump the entire HTML 

    return exampleInt; // Task<TResult> returns an object of type TResult, in this case int 
} 
相關問題