HttpWebRequest: Как найти почтовый индекс на канадской почте через WebRequest с приложением в форме x-www? - PullRequest
3 голосов
/ 18 сентября 2009

В настоящее время я пишу несколько тестов, чтобы улучшить свои навыки взаимодействия с Интернетом через Windows Forms. Один из таких тестов - найти почтовый индекс, который должен быть возвращен веб-сайтом Canada Post.

  1. Моя настройка URL по умолчанию: http://www.canadapost.ca/cpotools/apps/fpc/personal/findByCity?execution=e4s1
  2. Обязательные поля формы: streetNumber , streetName , город , провинция
  3. contentType является "application / x-www-form-closed"

РЕДАКТИРОВАТЬ: Пожалуйста, рассмотрите значение "application / x-www-form-encoded" вместо значения точки 3 в качестве contentType. (Спасибо EricLaw-MSFT!)

Результат, который я получаю, не является ожидаемым. Я получаю исходный код HTML страницы, на которой я могу вручную ввести информацию, чтобы найти почтовый индекс, но не исходный код HTML с найденным почтовым индексом. Есть идеи, что я делаю не так?

Должен ли я пойти по пути XML? Можно ли в первую очередь осуществлять поиск на канадской почте анонимно?

Вот пример кода для лучшего описания:

public static string FindPostalCode(ICanadadianAddress address) {
   var postData = string.Concat(string.Format("&streetNumber={0}", address.StreetNumber)
    , string.Format("&streetName={0}", address.StreetName)
    , string.Format("&city={0}", address.City)
    , string.Format("&province={0}", address.Province));

   var encoding = new ASCIIEncoding();
   byte[] postDataBytes = encoding.GetBytes(postData);
   request = (HttpWebRequest)WebRequest.Create(DefaultUrlSettings);
   request.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Anonymous;
   request.Container = new CookieContainer();
   request.Timeout = 10000;
   request.ContentType = contentType;
   request.ContentLength = postDataBytes.LongLength;
   request.Method = @"post";
   var senderStream = new StreamWriter(request.GetRequestStream());
   senderStream.Write(postDataBytes, 0, postDataBytes.Length);
   senderStream.Close();
   string htmlResponse = new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd();

   return processedResult(htmlResponse); // Processing the HTML source code parsing, etc.
}

Мне кажется, я застрял в горлышке бутылки с моей точки зрения. Я не нахожу выхода к желаемому результату.

РЕДАКТИРОВАТЬ: Кажется, есть параметры, как для ContentType этого сайта. Позвольте мне объяснить.

  • Есть один с мета-переменными, который предусматривает следующее:

meta http-equ = "Content-Type" content = "application / xhtml + xml, text / xml, text / html; кодировка = UTF-8"

  • И еще один код, который читается как:

form id = "fpcByAdvancedSearch: fpcSearch" name = "fpcByAdvancedSearch: fpcSearch" method = "post" action = "/ cpotools / apps / fpc / personal / findByCity? Execute = e1s1" enctype = "application / x-www- форм-urlencoded "

У меня следующий вопрос: к какому из них я должен привязываться?

Позвольте мне предположить, первый ContentType должен рассматриваться как второй только для другого запроса к функции или около того, когда данные публикуются?

РЕДАКТИРОВАТЬ: В соответствии с запросом, ближе к решению я перечислен под этим вопросом: WebRequest: Как найти почтовый индекс, используя WebRequest для этого ContentType = ”application / xhtml + xml, text / xml, text / html; кодировка = UTF-8” ?

Спасибо за любую помощь! : -)

Ответы [ 2 ]

1 голос
/ 18 сентября 2009

HTTPWebRequest будет возвращать содержимое URL-запроса. Если это HTML-страница, она вернет HTML-разметку. Если содержимое страницы является XML, то оно вернет разметку XML.

Похоже, вам нужен веб-сервис. Я бы посмотрел, есть ли на этом сайте какие-либо веб-версии для обработки запросов такого типа. Если они это сделают, то он вернет XML, разметку JSON в ответ на ваш запрос. В противном случае вы можете проанализировать вывод запроса.

1 голос
/ 18 сентября 2009

Я пытаюсь найти причину, по которой вы не используете класс WebClient: -

var fields = new NameValueCollection();
fields.Add("streetnumber", address.StreetNumber);
fields.Add("streetname", address.StreetName);
fields.Add("city", address.City);
fields.Add("province", address.Province);

var wc = new WebClient();
byte[] resultData = wc.UploadValues(url, fields);
string result = Encoding.Default.GetString(resultData);

Возможно, вы захотите проверить кодировку, используемую сервером при отправке результатов, если он использует UTF-8, измените последнюю строку на: -

string result = Encoding.UTF8.GetString(resultData);

Некоторые проблемы, которые я обнаружил в вашем оригинальном коде: -

  1. В первом поле стоит префикс &, которого там быть не должно.
  2. Вам необходимо вызывать Uri.EscapeDataString для каждого значения поля.
  3. Вы пытаетесь построить поток памяти вокруг результата GetRequestStream, я не вижу, чего бы это достигло, даже если бы у MemoryStream был такой конструктор, но в любом случае это не так. Просто напишите прямо в поток, возвращаемый GetRequestStream

Если вы уже сделали это, получите себе копию fiddler , чтобы вы могли наблюдать, что происходит, когда стандартная форма успешно запрашивает данные, и что делает ваш код.

Редактировать : Если у вас есть доказательства того, что из-за отсутствия контейнера cookie WebClient не работает, вы можете попробовать этот подход: -

public class MyWebClient : WebClient
{

    protected override WebRequest GetWebRequest (Uri address)
    {
      WebRequest request = (WebRequest) base.GetWebRequest (address);

      request.Container = new CookieContainer();
      return request;
    }
}

Теперь используйте мой код выше, но вместо этого используйте экземпляр WebClient instance MyWebClient.

...