WebRequest: Как найти почтовый индекс, используя WebRequest для этого ContentType="application/xhtml+xml, text/xml, text/html; charset=utf-8"?
Я впервые опубликовал это: HttpWebRequest: Как найти почтовый индекс на канадской почте через WebRequest с приложением в форме x-www?,
Следуя советам AnthonyWJones, я изменил свой код, следуя его советам.
Продолжая свой запрос, я заметил, что со временем тип контента Канадской почты, скорее всего, будет "application / xhtml + xml, text / xml, text / html; charset = utf-8".
Мои вопросы:
- Как нам сделать веб-запрос на такой веб-сайт типа контента?
- Должны ли мы продолжать работать с объектом NameValueCollection?
- Согласно Скотту Лэнсу, который щедро предоставил мне ценную информацию в моем предыдущем вопросе, WebRequest должен вернуть тип информации, какой бы ни был тип контента, я что-то здесь упускаю?
- Нужно ли менять код из-за изменения типа контента?
Вот мой код, чтобы было легче понять мой прогресс.
internal class PostalServicesFactory {
/// <summary>
/// Initializes an instance of GI.BusinessSolutions.Services.PostalServices.Types.PostalServicesFactory class.
/// </summary>
internal PostalServicesFactory() {
}
/// <summary>
/// Finds a Canadian postal code for the provided Canadian address.
/// </summary>
/// <param name="address">The instance of GI.BusinessSolutions.Services.PostalServices.ICanadianCityAddress for which to find the postal code.</param>
/// <returns>The postal code found, otherwise null.</returns>
internal string FindPostalCode(ICanadianCityAddress address) {
if (address == null)
throw new InvalidOperationException("No valid address specified.");
using (ServicesWebClient swc = new ServicesWebClient()) {
var values = new System.Collections.Specialized.NameValueCollection();
values.Add("streetNumber", address.StreetNumber.ToString());
values.Add("numberSuffix", address.NumberSuffix);
values.Add("suite", address.Suite);
values.Add("streetName", address.StreetName);
values.Add("streetDirection", address.StreetDirection);
values.Add("city", address.City);
values.Add("province", address.Province);
byte[] resultData = swc.UploadValues(@"http://www.canadapost.ca/cpotools/apps/fpc/personal/findByCity", "POST", values);
return Encoding.UTF8.GetString(resultData);
}
}
private class ServicesWebClient : WebClient {
public ServicesWebClient()
: base() {
}
protected override WebRequest GetWebRequest(Uri address) {
var request = (HttpWebRequest)base.GetWebRequest(address);
request.CookieContainer = new CookieContainer();
return request;
}
}
}
Этот код фактически возвращает исходный код HTML формы, которую необходимо заполнить необходимой информацией, чтобы выполнить поиск по почтовому индексу. Я хочу получить исходный код HTML или что-то еще с найденным почтовым индексом.
РЕДАКТИРОВАТЬ: Вот WebException, которое я получаю сейчас: "Невозможно отправить тело контента с этим типом глагола". (Это перевод с французского исключения "Невозможное общение с другими людьми")
Вот мой код:
internal string FindPostalCode(string url, ICanadianAddress address) {
string htmlResult = null;
using (var swc = new ServiceWebClient()) {
var values = new System.Collections.Specialized.NameValueCollection();
values.Add("streetNumber", address.StreetNumber.ToString());
values.Add("numberSuffix", address.NumberSuffix);
values.Add("suite", address.Suite);
values.Add("streetName", address.StreetName);
values.Add("streetDirection", address.StreetDirection);
values.Add("city", address.City);
values.Add("province", address.Province);
swc.UploadValues(url, @"POST", values);
string redirectUrl = swc.ResponseHeaders.GetValues(@"Location")[0];
=> swc.UploadValues(redirectUrl, @"GET", values);
}
return htmlResult;
}
Строка, которая вызывает исключение, указывается с "=>". Кажется, я не могу использовать GET в качестве метода, но это то, что мне сказали, чтобы я сделал...
Есть идеи, что мне здесь не хватает? Я пытаюсь сделать то, что Джастин (см. Ответ) рекомендовал мне сделать.
Заранее благодарю за любую помощь!:-)
1 ответ
В качестве введения в мир скрипа скриншотов, вы выбрали очень сложный случай! Страница просмотра поста в Канаде работает следующим образом:
- первая страница представляет собой форму, которая принимает значения адреса
- эта страница отправляет на второй URL.
- этот второй URL, в свою очередь, перенаправляет (используя перенаправление HTTP 302) на третий URL, который фактически показывает HTML-ответ, содержащий почтовый индекс.
Что еще хуже, страница на шаге 3 должна знать файл cookie, установленный на шаге 1. Так что вам нужно использовать то же самое CookieContainer
для всех трех запросов (хотя может быть достаточно отправить один и тот же CookieContainer
только № 2 и № 3).
Кроме того, вам может потребоваться отправить дополнительные HTTP-заголовки в этих запросах, например, Accept. Я подозреваю, что вы сталкиваетесь с проблемами в том, что HttpWebRequest по умолчанию обрабатывает перенаправление прозрачно для вас - но когда он прозрачно перенаправляет, он может не добавить правильные заголовки HTTP, необходимые для олицетворения браузера.
Решение состоит в том, чтобы установить HttpWebRequest
"s AllowAutoRedirect
свойство ложно, и обрабатывать перенаправление самостоятельно. Другими словами, как только первый запрос вернет перенаправление, вам нужно будет извлечь URL в HttpWebResponse
"s Location:
заголовок. Тогда вам нужно будет создать новый HttpWebRequest
(на этот раз обычный запрос GET, а не POST) для этого URL. Помните, чтобы отправить тот же файл cookie! (CookieContainer
класс делает это очень легко)
Вам также может потребоваться сделать дополнительный запрос (#1 в моем списке выше), чтобы настроить cookie сессии. Если бы я был вами, я бы предположил, что это необходимо, просто чтобы устранить это как проблему, и попробуйте удалить этот шаг позже и посмотреть, работает ли еще ваше решение.
Вы можете скачать и использовать Fiddler ( http://www.fiddlertool.com/), чтобы помочь вам со всем этим. Fiddler позволяет вам наблюдать за HTTP-запросами, передаваемыми по проводам, и позволяет (с помощью функции построителя запросов) создавать запросы HTTP, чтобы вы могли видеть, какие заголовки действительно требуются.