2009-09-21 9 views
3

Я первый опубликовал это: HttpWebRequest: How to find a postal code at Canada Post through a WebRequest with x-www-form-enclosed?.WebRequest: Как найти почтовый индекс с помощью WebRequest против этого ContentType = "application/xhtml + xml, text/xml, text/html; charset = utf-8"?

Следуя предложениям AnthonyWJones, я изменил свой код после его предложений.

В продолжение моего запроса я со временем заметил, что контент-тип Canada Post более вероятен быть «application/xhtml + xml, text/xml, text/html; charset = utf-8 ".

Мои вопросы:

  1. Как мы WebRequest против такого сайта с содержанием типа?
  2. Нужно ли продолжать работу с объектом NameValueCollection?
  3. Согласно Скотту Лэнсу, который щедро предоставил мне ценную информацию в моем предыдущем вопросе, WebRequest вернет тип информации независимо от типа содержимого, я что-то пропустил здесь?
  4. Должен ли я изменить свой код из-за изменения типа контента?

Вот мой код, чтобы было легче понять мой прогресс.

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 или что бы это ни было, с найденным почтовым кодом.

EDIT: Вот WebException я получаю сейчас: «Не удалось отправить тело содержимого с этим типом глагола.» (Это перевод с французского исключения «Impossible d'Envoyer ип кордебалет Contenu ауес се типа де Вербье.»)

Вот мой код:

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 как метод, но это то, что мне сказали, чтобы я сделал ...

Любая идея, что мне здесь не хватает? Я пытаюсь сделать то, что Джастин (см. Ответ) рекомендовал мне сделать.

Заранее благодарим за любую помощь! :-)

+0

@Will: пожалуйста, держите нас в курсе; очень заинтересованы в этом вопросе! У вас есть блог? –

+0

@pcambell: Спасибо за ваш интерес. Я буду информировать вас, добавив результаты моих исследований здесь, чтобы вы могли воспользоваться этим. –

+0

У вас есть полное решение? Работает? Я пытаюсь сделать то же самое здесь. Благодаря! – VinnyG

ответ

2

В качестве введения в мир скрининга экрана вы выбрали очень жесткий футляр! Страница поиска Canada Post работает следующим образом:

  1. первая страница является формой, которая принимает адрес значение
  2. этой страница сообщений для второго URL.
  3. этот второй URL-адрес, в свою очередь, перенаправляет (используя перенаправление HTTP 302) на третий URL-адрес, который фактически показывает вам ответ HTML, содержащий почтовый индекс.

Хуже того, страница на этапе №3 должна знать набор файлов cookie в шаге # 1. Поэтому вам нужно использовать один и тот же CookieContainer для всех трех запросов (хотя, возможно, будет достаточно отправить те же CookieContainer на # 2 и # 3).

Кроме того, возможно, вам придется отправить дополнительные HTTP-заголовки в эти запросы, например Accept. Я подозреваю, что вы столкнулись с проблемами в том, что HttpWebRequest по умолчанию обрабатывает прозрачно для вас прозрачность - но когда он прозрачно перенаправляет, он может не добавлять правильные заголовки HTTP, необходимые для олицетворения браузера.

Решение должно установить значение HttpWebRequestAllowAutoRedirect в false и обрабатывать перенаправление самостоятельно. Другими словами, как только первый запрос возвращает перенаправление, вам нужно вытащить URL-адрес в заголовке . Затем вам нужно будет создать новый HttpWebRequest (на этот раз обычный GET-запрос, а не POST) для этого URL-адреса. Помните, чтобы отправить тот же файл cookie! (класс CookieContainer делает это очень просто)

Возможно, вам понадобится сделать дополнительный запрос (№ 1 в моем списке выше), чтобы настроить файл cookie сеанса. Если бы я был вами, я бы предположил, что это требуется, просто чтобы устранить его как проблему, и попробуйте удалить этот шаг позже и посмотреть, работает ли ваше решение.

Вы хотите загрузить и использовать Fiddler (www.fiddlertool.com), чтобы помочь вам в этом. Fiddler позволяет вам просматривать HTTP-запросы, проходящие через провод, и позволяет вам (через функцию построителя запросов) создавать HTTP-запросы, чтобы вы могли видеть, какие заголовки действительно необходимы.

+0

@ Юстин Грант: Большое спасибо за эту информацию. Я загрузил и установил Fiddler уже по предложению AnthonyWJones и EricLaw-MSFT. Я просто не понимаю все это с заголовками и всем остальным. Я знал о переадресации, но я не знал, как обрабатывать в моем конкретном случае. Ваши реплики наверняка помогут мне узнать теперь, что мне лучше справиться с редиксами. Ваш ответ более чем завершен. Надеюсь, я справлюсь с этим решением. Если вы не возражаете, пожалуйста, вернитесь, чтобы узнать, не отправил ли я что-нибудь еще, вопрос, комментарий .. –

+0

@Justin Grant: Что касается второго и третьего запросов, просто мне нужно запустить другой запрос из URL-адреса ответа, используя тот же экземпляр ServicesWebClient, который я закодировал? Как получить этот URL-адрес ответа, чтобы я мог снова загрузить данные на этот адрес, чтобы выполнить второй запрос? –

+1

Hi Will - есть две возможности. Если URL-адреса всегда одинаковые (что, я думаю, имеет место на сайте Canada Post), вы можете просто скорректировать URL-адреса для каждого шага вашего кода. Если они отличаются друг от друга каждый раз, вам нужно будет очистить HTML-код, чтобы найти URL-адреса. Вы можете использовать один и тот же экземпляр WebClient или другой. Просто убедитесь, что вы настраиваете cookie и заголовки правильно для каждого шага. –