C# POST主体中的JSON然后提取响应主体以获取访问令牌

C# POST主体中的JSON然后提取响应主体以获取访问令牌,c#,C#,我有一个去年编写的小型Python应用程序,需要用C#重新制作。我不太了解C,但是需要在动态365和QueBook桌面之间建立连接,使用C(或C++,java,VB……我都不知道)。 正如我所说的,Python应用程序工作得很好,我通过Postman从D365获得了我所需要的,我花了很多时间让它为C#工作。有一个示例项目,但试图解释正在发生的事情让我头晕目眩(它也不会运行,否则我只会使用它) 这就是我目前所做的: class Program { static void Main(stri

我有一个去年编写的小型Python应用程序,需要用C#重新制作。我不太了解C,但是需要在动态365和QueBook桌面之间建立连接,使用C(或C++,java,VB……我都不知道)。 正如我所说的,Python应用程序工作得很好,我通过Postman从D365获得了我所需要的,我花了很多时间让它为C#工作。有一个示例项目,但试图解释正在发生的事情让我头晕目眩(它也不会运行,否则我只会使用它)

这就是我目前所做的:

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;
        }
    }
}
Visual Studio Community 2017将停止在该行上运行,并且不会触发任何类型的错误。我将在那里发送一个断点,然后是F10或F11,它将退出程序

发现了与此相关的问题:

打开了所有选项,但仍然看不出它为什么刚刚结束

这是我在《邮递员》中所做工作的截图。很明显,我只是在C#中做错了什么


将事情立即结合起来,您不会等待
您的
PostAsync
呼叫,因此不会真正存储响应

其次,当你告诉C#写控制台时,它不会自动序列化这样的对象,所以它只是告诉你它是什么类型的对象,也就是包装
HttpResponseMessage
的任务

下面应该是响应主体(假设它只是一个标记,这对您来说很好)。您需要对其进行一些修改,以使其完全适合您,但这应该可以让您开始

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

尝试以下操作以获取响应的内容:

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

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

string responseContent = await response.Content.ReadAsStringAsync();
首先,您需要等待
调用
PostAsync()。由于这只剩下一个
HttpResponseMessage
,而不是响应的实际内容,因此您必须在第二步中以字符串形式读取响应的content属性来获取它

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


我假设您的
access\u令牌
是此接收字符串中的一个JSON属性,因此您必须将其反序列化或使用提取机制从所述字符串中获取实际的
access\u令牌
。StackOverflow上已经有很多关于这个的帖子,所以我不再详细说明了。

嗨,谢谢。我已经根据你的建议更新了我的问题。嗨,谢谢。我已经在测试你的建议的基础上更新了我的问题。我只是简单地提醒一下,你是在控制台上做这件事的,对吗?
Main
方法中的代码块完成后,控制台将关闭/进程结束。由于
ConnectToCRM
调用异步方法
HttpRequestToCrm
Main
中的代码在异步方法完成之前完成。因此,在异步方法完成之前,进程将关闭。添加
Console.ReadLine()
ConnectToCRM()之后调用应保持控制台打开/进程运行。让我知道这是否是问题所在!嘿,在那儿!我想得到的一切。谢谢你的帮助@(没问题:)大多数时候,问题都发生在我们最意想不到的地方!
HttpResponseMessage response = await client.PostAsync(tokenEndPoint, content);

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

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