POST正文中的JSON,然后提取响应的正文以获取access_token

时间:2018-12-07 21:24:58

标签: c#

我有一个我去年编写的Python小应用程序,需要在C#中重新制作。我不是很了解C#,但是需要在Dynamics 365和使用C#(或C ++,Java,VB ...我都不知道)的QuickBooks Desktop之间建立连接。

正如我所说,Python应用程序运行良好,并且可以通过Postman从D365中获得所需的东西,而让它有时间在C#中工作。有一个示例项目here,但是试图解释正在发生的事情却使我很头疼(它不会运行,否则我只会使用它)。

这是我目前正在做的事情:

class Program
{
    static void Main(string[] args)
    {
        ConnectToCRM();
    }

    static void ConnectToCRM()
    {
        string crmOrg = "https://company.api.crm.dynamics.com";
        string clientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
        string clientSecret = "super_secret_stuff";
        string username = "me@company.biz";
        string userPassword = "password";
        string authorizationEndPoint =
            "https://login.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/oauth2/authorize";
        string crmWebApi = "https://company.api.crm.dynamics.com/api/data/v8.2";

        var values = new Dictionary<string, string>
            {
                {"client_id", clientId},
                {"client_secret", clientSecret},
                {"resource", crmOrg},
                {"oauthUrl", authorizationEndPoint},
                {"username", username},
                {"password", userPassword},
                {"grant_type", "password"}
            };

        HttpRequestToCrm(values);
    }

    public class ServerResponse
    {
        public string token_type { get; set; }
        public string scope { get; set; }
        public string expires_in { get; set; }
        public string ext_expires_in { get; set; }
        public string expires_on { get; set; }
        public string not_before { get; set; }
        public string resource { get; set; }
        public string access_token { get; set; }
        public string refresh_token { get; set; }
    }

    static async void HttpRequestToCrm(Dictionary<string, string> values)
    {
        string tokenEndPoint = "https://login.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/oauth2/token";

        var client = new HttpClient();

        var content = new FormUrlEncodedContent(values);

        try
        {
            HttpResponseMessage response = await client.PostAsync(tokenEndPoint, content);
            var responseContent = await response.Content.ReadAsStringAsync();

            Console.WriteLine(response);
            Console.WriteLine(responseContent);

            ServerResponse rb = JsonConvert.DeserializeObject<ServerResponse>(responseContent);

            Console.WriteLine(rb.token_type);
        }
        catch (WebException e)
        {
            Console.WriteLine("catch");

            Console.WriteLine(e);
            throw;
        }
    }
}

据我了解,我需要为FormUrlEncodedContent使用x-www-form-urlencoded,因为x-www-form-urlencoded是我在Postman中要做的工作。 Python似乎正在这样做。

Console.WriteLine(content);只是说System.Net.Http.FormUrlEncodedContentConsole.WriteLine(response);实际上现在有一些东西,以前没有:System.Threading.Tasks.Task 1 [System.Net.Http.HttpResponseMessage] . I need to get the response body, so that I can get the access_token`,然后最终实际上查询了D365网站API。

如何获取响应正文和access_token?我什至怎么看这就是它的回应?我的方法完全错误吗?

编辑:

我是否这样做:

HttpResponseMessage response = await client.PostAsync(tokenEndPoint, content);

或者:

var response = await client.PostAsync(tokenEndPoint, content);

Visual Studio Community 2017在该行退出运行,并且不会触发任何类型的错误。我将在此处发送一个断点,然后是F10或F11,它会退出程序。

发现与此有关:

Code Execution stops with no error

打开所有选项,但仍然看不到为什么只是结束。

这是我要在Postman中工作的屏幕截图。显然我在C#中做错了。

enter image description here

2 个答案:

答案 0 :(得分:1)

立即解决问题,您不会awaitPostAsync电话,因此您实际上并没有存储响应。

第二,当您告诉C#将其写入控制台时,C#不会自动序列化对象,因此它只是告诉ou这是什么类型的对象,也就是包装HttpResponseMessage的任务。 / p>

以下内容将使您获得响应正文(假设它只是令牌,对您而言将很好地工作)。您需要对其进行一些修改以使其完全适合您,但这应该可以帮助您入门。

try
{
    var response = await client.PostAsync(tokenEndPoint, content);
    //read the response body as a string here
    string token = await response.Content.ReadAsStringAsync();
    Console.WriteLine(response);

}
catch (WebException e)
{
    Console.WriteLine("catch");

    Console.WriteLine(e);
    throw;
}

答案 1 :(得分:1)

尝试此操作以获得响应的内容:

HttpResponseMessage response = await client.PostAsync(tokenEndPoint, content);

if(!response.IsSuccessStatusCode) return; // optional

string responseContent = await response.Content.ReadAsStringAsync();

首先,您需要await进行PostAsync()呼叫。由于仅留下HttpResponseMessage而不是响应的实际内容,因此您必须在第二步中通过将响应的Content属性读取为字符串来获取它。

如果您的响应返回了OK(HTTP 200状态代码),则此代码应使您responseContent保留所需的响应作为字符串。

我假设您的access_token是此接收到的字符串中的JSON属性,因此您必须对其进行反序列化或使用提取机制从所述字符串中获取实际的access_token。关于此,StackOverflow上已经有很多帖子,所以我将不再赘述。