简体   繁体   English

HTTP Post Request返回400 C#

[英]HTTP Post Request returns 400 C#

I am trying to make a http post request to obtain an api token. 我正在尝试发出http post请求以获取api令牌。 If successful, it is supposed to return string values of access token, token type (bearer) and expires_in. 如果成功,则应返回访问令牌,令牌类型(承载)和expires_in的字符串值。

The code I have is a generic one which I was expecting to see working. 我所拥有的代码是一个通用的代码,我期待它能够正常工作。 But for some reasons, it throws an exception of 400 "The remote server returned an error. Bad Request". 但由于某些原因,它抛出400“异常远程服务器返回错误。错误请求”。 I have been trying everything to fix this whereas the result doesn't change. 我一直在努力解决这个问题,但结果并没有改变。

When I debug the code and see the result in the Output window, there is an exception about Data stream saying "this stream doesn't support seek operations" 当我调试代码并在“输出”窗口中查看结果时,有一个关于数据流的例外,说“此流不支持搜索操作”

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

My doubt is it happens due to the postData, the way it is encoded. 我怀疑它是由于postData,它的编码方式而发生的。 My client secret is something like: 我的客户秘密是这样的:

g/gOvqf5R+FTZZXbwsCbp0WsQjF9B0bl87IBQ8VAJ2Q= 克/ gOvqf5R + FTZZXbwsCbp0WsQjF9B0bl87IBQ8VAJ2Q =

Does it encode the characters in the secret itself so that it constructs a bad request? 它是否对秘密本身的字符进行编码,以便构造错误的请求?

I have also tried this on POSTMAN and it produced a result, so there is nothing with the api. 我也在POSTMAN上尝试了这个,它产生了一个结果,所以没有api。 It comes down again to the request content. 它再次归结为请求内容。 It's a console app. 这是一个控制台应用程序。 I am pasting my code below and I am thankful for your help in advance. 我正在粘贴下面的代码,我很感谢您的帮助。

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

    }

The remote server is giving you a 400 error due to you sending it incorrect data of some sort. 由于您发送了某种不正确的数据,远程服务器会给您400错误。 You may be able to get the response and figure out the exact error - the remote server would quite possibly give you some more information. 您可能能够获得响应并找出确切的错误 - 远程服务器很可能会为您提供更多信息。 However, I can see one issue with your post data - the client secret needs to be URL encoded. 但是,我可以看到您的帖子数据存在一个问题 - 客户端密钥需要进行URL编码。 Look at the content of it and you will see that it ends with an = sign. 查看它的内容,你会看到它以=符号结尾。 that will be interpreted as a special character. 这将被解释为一个特殊的角色。 I also like to be a bit more explicit about creating strings, so this would work for you: 我也想更明确地创建字符串,所以这对你有用:

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

Client id and secret had to be url encoded separately while forming form data. 客户端ID和秘密必须在形成表单数据时单独进行url编码。 Updated postData: 更新了postData:

string postData = "grant_type=client_credentials&client_id=" + HttpUtility.UrlEncode(appSettings["my_client_id"]) + "&client_secret=" + HttpUtility.UrlEncode(appSettings["my_client_secret"]);

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

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