简体   繁体   English

通过使用C#和HttpClient调用REST API来检索JSON内容

[英]Retrieving JSON content by calling a REST API with C# and HttpClient

I'm having a stab at some mobile development with Xamarin and C#. 我正在使用Xamarin和C#进行一些移动开发。 I'm building a simple login screen for an Android app and I'm using the HttpClient to make the actual calls but I'm stuck on some of the details to get it to work. 我正在为一个Android应用程序构建一个简单的登录屏幕,我正在使用HttpClient进行实际调用,但我仍然坚持一些细节以使其工作。

I have set up a simple Client class that represents my API client: 我已经设置了一个代表我的API客户端的简单Client类:

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;
            }
        }
    }
}

As you can see, the authenticate method uses a POST to create a new session on the server. 如您所见, authenticate方法使用POST在服务器上创建新会话。 The /auth endpoint returns a JSON blob with a token and a timeout value. /auth端点返回带有令牌和超时值的JSON blob。

This is how the authenticate method is called: 这是authenticate方法的调用方式:

Client myClient = new Client();

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

var content = contentTask.ToString();

Console.Out.WriteLine(content);

My content never outputs anything. 我的content从不输出任何content I'm obviously (and without a doubt) doing various things wrong. 我显然(毫无疑问)做了各种错误的事情。

How can I have my authenticate method return the JSON string I expect? 如何让我的authenticate方法返回我期望的JSON字符串?

I have been using these sources for inspiration: 我一直在使用这些来源获取灵感:

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 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-网络客户端

Since you are returning a Task and not just a string you need to wait upon the myclient.authenticate method. 由于您要返回一个Task而不仅仅是一个string您需要等待myclient.authenticate方法。

You wouldnt have to wait if you retruned a string . 如果你重新编写一个string你就不必等待。 Which I think is possible in your case, by just changing the return type from Task<string> to string . 我认为在您的情况下,只需将返回类型从Task<string>更改为string

your Clent authenticate method : 你的Clent 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;
            }
        }
    }

Consume the Client as : 将客户消费为:

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);
}

The sample code is already present in the source of inspiration 示例代码已经存在于灵感源中

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
}

authenticate()是一种异步方法,因此您需要等待它

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM