C#使用HttpClient与Nest API Restful Auth一起使用

时间:2016-11-01 16:39:38

标签: c# .net dotnet-httpclient

仍然是C#的新手,我确信我没有正确使用HttpClient库。我正在尝试使用Works With Nest API进行身份验证,以便我可以读取/写入恒温器的请求。以下是我用于验证的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using System.Net.Http;
using System.Net.Http.Headers;


namespace iConnect.Controllers
{
    public class NestController : Controller
    {
        static HttpClient client = new HttpClient();

        public IActionResult Index()
        {
            return View();
        }

        public async Task<HttpResponseMessage> GetNestAuthCode()
        {
            // Nest Pin Code
            String pincode = "MYPING";
            String clientID = "My-Client-ID";
            String clientSecret = "MySecretString";
            String grantType = "authorization_code";

            client.BaseAddress = new Uri("https://api.home.nest.com");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            var request = new HttpRequestMessage(HttpMethod.Post, "/oauth2/access_token");

            var data = new List<KeyValuePair<string, string>>
            {                
                new KeyValuePair<string, string>("code", pincode)
                , new KeyValuePair<string, string>("client_id", clientID)
                , new KeyValuePair<string, string>("client_secret", clientSecret)
                , new KeyValuePair<string, string>("grant_type", grantType)
            };

            //var content = new FormUrlEncodedContent(data);
            //await content.ReadAsByteArrayAsync();
            //content.Add(data);
            request.Content = new FormUrlEncodedContent(data);

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

            HttpResponseMessage response = await client.SendAsync(request);

            return response;
        }
    }
}

当我转到localhost:9387 / Nest / GetAuthCode时,我收到以下JSON响应:

{
   "version":{
      "major":1,
      "minor":1,
      "build":-1,
      "revision":-1,
      "majorRevision":-1,
      "minorRevision":-1
   },
   "content":{
      "headers":[
         {
            "key":"Content-Type",
            "value":[
               "application/json"
            ]
         }
      ]
   },
   "statusCode":400,
   "reasonPhrase":"Bad Request",
   "headers":[
      {
         "key":"Connection",
         "value":[
            "keep-alive"
         ]
      }
   ],
   "requestMessage":{
      "version":{
         "major":1,
         "minor":1,
         "build":-1,
         "revision":-1,
         "majorRevision":-1,
         "minorRevision":-1
      },
      "content":{
         "headers":[
            {
               "key":"Content-Type",
               "value":[
                  "application/x-www-form-urlencoded"
               ]
            },
            {
               "key":"Content-Length",
               "value":[
                  "130"
               ]
            }
         ]
      },
      "method":{
         "method":"POST"
      },
      "requestUri":"https://api.home.nest.com/oauth2/access_token",
      "headers":[
         {
            "key":"Accept",
            "value":[
               "application/json"
            ]
         }
      ],
      "properties":{

      }
   },
   "isSuccessStatusCode":false
}

非常感谢任何帮助。谢谢。

修改

我做了以下更改并得到以下回复(这不是我的预期):

代码:

public async Task<ActionResult> GetNestAuthCode()
        {
            // Nest Pin Code
            String pincode = "MYPING";
            String clientID = "My-Client-ID";
            String clientSecret = "MySecretString";
            String grantType = "authorization_code";

            client.BaseAddress = new Uri("https://api.home.nest.com");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            //var request = new HttpRequestMessage(HttpMethod.Post, "/oauth2/access_token");

            var data = new List<KeyValuePair<string, string>>
            {                
                new KeyValuePair<string, string>("code", pincode)
                , new KeyValuePair<string, string>("client_id", clientID)
                , new KeyValuePair<string, string>("client_secret", clientSecret)
                , new KeyValuePair<string, string>("grant_type", grantType)
            };

            //var content = new FormUrlEncodedContent(data);
            //await content.ReadAsByteArrayAsync();
            //content.Add(data);
            //request.Content = new FormUrlEncodedContent(data);

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

            var response = await client.PostAsync("oauth2/access_token",
                    new FormUrlEncodedContent(data));

            var content = await response.Content.ReadAsStringAsync();

            return Content(content);
        }

响应:

{"error":"oauth2_error","error_description":"authorization code not found","instance_id":"f64d5268-8bec-4799-927c-e53454ed96d5"}

1 个答案:

答案 0 :(得分:1)

您将从操作方法返回整个响应消息及其所有属性和值。相反,您应该只阅读其内容并将其返回。如果您愿意,可以找到关于使用内置.NET HttpClient权限here的好文章。

我会做的是以下内容:

public async Task<IActionResult> GetNestAuthCode()
{
    // HttpClient setup...

    var content = new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>("code", "MYPING"),
        new KeyValuePair<string, string>("client_id", "My-Client-ID"),
        new KeyValuePair<string, string>("client_secret", "MySecretString"),
        new KeyValuePair<string, string>("grant_type", "authorization_code")
    });

    var response = await client.PostAsync("oauth2/access_token", content);

    // Or check instead with IsSuccessStatusCode
    response.EnsureSuccessStatusCode();

    // ReadAsStringAsync() is just an example here
    var responseContent = await response.Content.ReadAsStringAsync();

    return Content(responseContent);
}

请注意......

  • 我仍然使用IActionResult(或实际Task<IActionResult>)作为返回类型。 您不应该返回响应对象。
  • 我直接使用PostAsync()方法,相关内容为FormUrlEncodedContent,而不是先构建HttpRequestMessage并使用SendAsync()
  • 也不要忘记检查您的请求是否成功!否则,您可能会从操作方法返回错误消息。
  • 我只是以ReadAsStringAsync()return Content()为例。

请注意,您对Nest API的请求有问题,因为它返回400 Bad Request。您应该能够从内容中的错误消息中精确地得到什么。 ;)

修改

我非常快速地了解了Nest API,我认为您为code提供了错误的值。我认为您应该首先调用另一个API方法来检索授权代码,然后才能将其替换为访问令牌(如here所示),而不是指定您的PIN码。