#c#
#c#
Вопрос:
Я изучаю C # и веб-запросы, поэтому я хотел начать с простого post и просто распечатать ответ на консоль.
Я дважды проверил запросы в Chrome и с помощью fiddler, и я получаю там правильный ответ, но в этой программе он возвращает «отказано в доступе».
static async Task<string> GetWeatherAsync()
{
var values = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("User-Agent", "WeatherAhead")
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("https://api.weather.gov/points/39.7456,-97.0892", content);
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
URL-адрес является тестовым, который они предоставляют в weather.gov документация и возвращает json, который я ожидаю, когда получаю доступ к нему через браузер.
Спасибо за любую помощь или предложения, которые вы можете предоставить!
Комментарии:
1. Вы вошли в систему в браузере? Может произойти какая-то аутентификация.
2. Если вы сделаете тот же точный запрос через C #, который вы делаете через браузер или Postman, вы получите тот же ответ. Их сервер не может определить разницу. Это означает, что вам не удалось выполнить одинаковые запросы. Итак, выясните, что вы делаете по-другому. Такие инструменты, как Fiddler, могут помочь вам в этом. Проверьте заголовки HTTP специально.
3. Да, я использовал Fiddler, чтобы попытаться имитировать заголовки, но, основываясь на ответе @Hien Nguyen, я ошибался. Хотел бы я сказать, что знаю, почему мой был неправильным, но я просмотрел несколько методов, чтобы попытаться выяснить это.
Ответ №1:
Добавьте эти настройки для клиента
client.BaseAddress = new Uri("http://api.weather.gov");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("User-Agent", "web api client");
Измените свою функцию на эту, и она сработала
static async Task < string > GetWeatherAsync() {
client.BaseAddress = new Uri("http://api.weather.gov");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("User-Agent", "web api client");
//var response = await client.GetAsync("https://api.weather.gov/points/39.7456,-97.0892");
var response = await client.GetAsync("/points/39.7456,-97.0892");
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
Комментарии:
1. в рабочей среде вы не хотите создавать экземпляр нового клиента с каждым запросом. это должен быть статический доступ только для чтения на уровне класса. смотрите здесь learn.microsoft.com/en-us/dotnet/api /…
2. @Sean Даже этого недостаточно для безопасного использования HttpClient. См. Эту статью . Отчасти поэтому я использую Flurl . Они учли эти проблемы и облекли их в приятный беглый синтаксис.
3. @Привет, код, который вы показали, — это совершенно неправильный способ использования HttpClient. Утверждение, что это просто пример кода, не оправдывает этого. Почему вы привели неправильный пример кода? Весь смысл в том, чтобы показать правильный способ выполнения действий, а не неправильный. Особенно, когда вы пытаетесь предоставить авторитетный ответ. Это нормально, если вы не знаете правильного пути, HttpClient особенно сложен. Но как только вам сказали, что вы делаете это неправильно, исправьте свой ответ!
4. Привет и @mason, спасибо, теперь это работает! Я добавил ConnectionLeaseTimeout, как это было предложено в статье, на которую вы ссылались. Хотя это может не оказывать никакого влияния на такой базовый код, как этот, кажется, что было бы неплохо привыкнуть к этому.
5. @Aszuul Попробуйте Flurl : он проще, чем использование HttpClient, и учитывает такие мелочи, как время ожидания аренды соединения. И он легко преобразует ответ из JSON в объект для вас.