4

我正在尝试发出 http 发布请求以获取 api 令牌。如果成功,它应该返回访问令牌、令牌类型(承载)和 expires_in 的字符串值。

我拥有的代码是我期望看到的通用代码。但由于某些原因,它会抛出 400 “远程服务器返回错误。错误请求”的异常。我一直在尝试一切来解决这个问题,而结果并没有改变。

当我调试代码并在输出窗口中查看结果时,数据流出现异常,提示“此流不支持查找操作”

Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();

我怀疑它的发生是由于 postData,它的编码方式。我的客户秘密是这样的:

g/gOvqf5R+FTZZXbwsCbp0WsQjF9B0bl87IBQ8VAJ2Q=

它是否对密钥本身中的字符进行编码,以便构造一个错误的请求?

我也在 POSTMAN 上尝试过这个并产生了结果,所以 api 没有任何内容。它再次归结为请求内容。这是一个控制台应用程序。我在下面粘贴我的代码,并提前感谢您的帮助。

public static APIModel GenerateApiKey()
    {
        var appSettings = ConfigurationManager.AppSettings;

        try
        {
            var urlToCall = string.Format("https://app.example.com/token");
            var uri = new Uri(urlToCall);

            var request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = "POST";

            string postData = "grant_type=client_credentials&client_id=" + appSettings["my_client_id"] + "&client_secret=" + appSettings["my_client_secret"];
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);

            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = byteArray.Length;


            Stream dataStream = request.GetRequestStream();
            dataStream.Write(byteArray, 0, byteArray.Length);
            dataStream.Close();

            var response = (HttpWebResponse)request.GetResponse();

            APIModel bearerToken;

            using (StreamReader sr = new StreamReader(response.GetResponseStream()))
            {
                string jsonFromServer = sr.ReadToEnd();
                bearerToken = JsonConvert.DeserializeObject<APIModel>(jsonFromServer); 
            }

            response.Close();

            return bearerToken;

        }
        catch (Exception e)
        {
            throw new Exception("Error getting a response from API  " + e.Message);
        }

    }
4

2 回答 2

2

由于您向远程服务器发送了某种不正确的数据,远程服务器给您一个 400 错误。您可能能够获得响应并找出确切的错误 - 远程服务器很可能会给您更多信息。但是,我可以看到您的帖子数据存在一个问题 - 客户端密码需要进行 URL 编码。查看它的内容,您会看到它以一个=符号结尾。这将被解释为特殊字符。我也喜欢更明确地创建字符串,所以这对你有用:

var postItems = new List<KeyValuePair<string, string>>
{
    new KeyValuePair<string, string>("grant_type", "client_credentials"),
    new KeyValuePair<string, string>("client_id", "client_credentials"),
    new KeyValuePair<string, string>("client_secret", "client_credentials"),
};

string postData = string.Join("&", 
    postItems.Select (kvp => 
        string.Format("{0}={1}", kvp.Key, HttpUtility.UrlEncode(kvp.Value))));
于 2015-07-09T13:47:34.067 回答
0

在形成表单数据时,客户端 ID 和密码必须分别进行 url 编码。更新后的数据:

string postData = "grant_type=client_credentials&client_id=" + HttpUtility.UrlEncode(appSettings["my_client_id"]) + "&client_secret=" + HttpUtility.UrlEncode(appSettings["my_client_secret"]);
于 2015-07-09T13:46:20.273 回答