1

Второй день не могу совладать с API сайта https://smmok-fb.ru/. Дело в том, чтобы получить API ключ мне нужно отправить массив с учетными данными(mail, password) в ответе в виде строки JSON я должен получить ключ. Но в итоге никак не получается отправить запрос должным образом, прошу помочь с отправкой POST запроса.

URL API - http://smmok-fb.ru/api/getApiKey Документация к API - https://smmok14.ru/api_docs

Класс для десерилизация JSON:

public class RequestSMMOK
{
[JsonProperty("status")]
public int Status { get; set; }
[JsonProperty("error")]
public string Error { get; set; }

[JsonProperty("respond")]
public Respond[] Respond { get; set; }

} public class Respond { [JsonProperty("api_key")] public string ApiKey { get; set; }

}

Мой пример кода:

        using (HttpClient client = new HttpClient())
        {
            client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            HttpContent content = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("email", "value@value.ru"),
            new KeyValuePair&lt;string, string&gt;(&quot;password&quot;,&quot;value&quot;)
        });
        content.Headers.ContentType = new MediaTypeHeaderValue(&quot;application/x-www-form-urlencoded&quot;);
        var responseMessage =
            await client.PostAsync(&quot;http://smmok-fb.ru/api/getApiKey&quot;, content);

        var result = JsonConvert.DeserializeObject&lt;RequestSMMOK&gt;(responseMessage.Content.ReadAsStringAsync().Result);
        return result;
    }

Что я получаю в итоге в ответе - {"status":400,"error":"\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d email"}"

  • 1
    Зачем вы указываете MediaType, если это делает за вас FormUrlEncodedContent? Также почему .Result, ведь у вас используется async/await? – EvgeniyZ Jul 05 '20 at 10:13

2 Answers2

1
  1. Не надо создавать HttpClient на каждый запрос.
  2. IDisposable классы надо оборачивать в using или диспозить вручную.
  3. FormUrlEncodedContent автоматически настроит Content-Type, не нужно это делать вручную
  4. .Result в асинхронном коде - это ошибка, используйте await

Разберу на примере.

Объявите HttpClient отдельно, один раз на все время работы программы.

private static readonly HttpClient client = new HttpClient();

Eсли вам нужен User-Agent, добавьте его тоже в конструкторе класса, один раз. Но я не уверен, что он вообще вам нужен, попробуйте сначала без него.

client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");

Ну и сам метод.

private async Task<T> PostAPIData<T>(string url, Dictionary<string, string> data)
{
    using (HttpContent content = new FormUrlEncodedContent(data))
    using (HttpResponseMessage responseMessage = await client.PostAsync(url, content).ConfigureAwait(false))
    {
        string jsonText = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
        return JsonConvert.DeserializeObject<T>(jsonText);
    }
}

Вызов

Dictionary<string, string> postData = new Dictionary<string, string>();
postData.Add("email", "value@value.ru");
postData.Add("password","value");
RequestSMMOK result = await PostAPIData<RequestSMMOK>("https://smmok-fb.ru/api/getApiKey", postData);

Вот здесь еще ошибка, не нужен массив, исправьте вот так

[JsonProperty("respond")]
public Respond Respond { get; set; }

Допишу сюда:

Причина ошибки была в том, что сервер хочет HTTPS запрос, а не HTTP, хотя в документации к API это не указано. Изменили ссылку на https://, и все заработало.

aepot
  • 49,560
  • Спасибо большое за разбор! Но, переписав полностью Ваш пример кода, так-же ответ с зарубежного SO я получаю в итоге то, что получал раннее. Ошибку, что данные не были переданы. – FERROUS SAGE Jul 05 '20 at 11:23
  • @FERROUSSAGE значит ошибка за пределами того кода, что вы показали, и я вам исправил. Ну это при условии, что вы в точности как я написал пробуете. Так как я не вижу остальной код, я не могу больше ничего подсказать. – aepot Jul 05 '20 at 11:32
  • Более кода нет, это весь код, который был. Пробую в максимальной точности, добавляя email&password в словарь – FERROUS SAGE Jul 05 '20 at 11:37
  • В любом случае спасибо Вам и всем остальным участникам, с другими API все работает, хотя и до этого с моим плохим кодом не было проблем с ними) – FERROUS SAGE Jul 05 '20 at 11:50
  • @FERROUSSAGE я нашел, как это исправить, замените "http" на "https". И сервер вам начнет нормально отвечать. Мне вот что ответил Пользователь с указанным сочетанием логин\пароль не найден – aepot Jul 05 '20 at 11:51
  • 1
    Да, в этом была проблема!! Спасибо большое:) – FERROUS SAGE Jul 05 '20 at 11:52
  • @FERROUSSAGE вы заметили, что у вас ошибка в классе данных? Я внизу ответа дописал. – aepot Jul 05 '20 at 11:54
  • Да, заметил:) Еще раз спасибо) – FERROUS SAGE Jul 05 '20 at 11:55
  • @FERROUSSAGE как я и предполагал, User-Agent переопределять не нужно. – aepot Jul 05 '20 at 11:57
0

Если перевести коды символов utf-8 в строку, то сервер отвечает: "Не указан email". Попробуйте через Fiddler посмотреть что в реальности отправляется на сервер. Может он хочет email в другом поле, тут сложно сходу разобраться.

CrazyElf
  • 71,194
  • Спасибо за ответ! По Вашему совету я посмотрел в программе Fiddler, что отправляется на сервер и увидел, что данные отправляются как надо и на выходе я получил API ключ. Тогда я не понимаю, что я делаю не так в IDE, если я не получаю API ключа там – FERROUS SAGE Jul 05 '20 at 08:55
  • вот ссылка на скриншот - https://yadi.sk/i/xJZyQ5_q0xoL-Q – FERROUS SAGE Jul 05 '20 at 09:04
  • 2
    @FERROUSSAGE Как вы можете в Fiddler видеть успешно отправленный запрос, если в программе у вас совершенно другой ответ? Вы проверяйте не то, что через браузер или сторонний софт отправляете, а то, что отправляет ваше приложение! – EvgeniyZ Jul 05 '20 at 10:12