HttpWebRequest: Comment trouver un code postal à Postes Canada grâce à un WebRequest avec x-www-form-closed?

StackOverflow https://stackoverflow.com/questions/1444563

Question

J'écris actuellement des tests afin d'améliorer mes compétences en interaction Internet à travers Windows Forms. L’un de ces tests consiste à trouver un code postal qui devrait être renvoyé par le site Web de Postes Canada.

  1. Mon paramètre d'URL par défaut est défini sur: http: / /www.canadapost.ca/cpotools/apps/fpc/personal/findByCity?execution=e4s1
  2. Les champs de formulaire obligatoires sont les suivants: numéro de rue , nom de rue , ville , province
  3. .
  4. Le type de contenu est "application / x-www-form-closed"
  5. .
  

EDIT: tenez compte de la valeur " application / x-www-form-encoded " au lieu de la valeur du point 3 comme contentType. (Merci EricLaw-MSFT!)

     

Le résultat obtenu n’est pas celui escompté. Je reçois le code source HTML de la page où je pourrais saisir manuellement les informations pour trouver le code postal, mais pas le code source HTML avec le code postal trouvé. Une idée de ce que je fais mal?

     

Dois-je envisager d’utiliser la méthode XML? Est-il tout d'abord possible de rechercher anonymement sur Postes Canada?

Voici un exemple de code pour une meilleure description:

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.
}

Je semble coincé dans un goulot de bouteille à mon point de vue. Je ne trouve aucun moyen de parvenir au résultat souhaité.

  

EDIT: Il semble que des paramètres soient à définir pour le type de contenu de ce site. Laissez-moi vous expliquer.

  • Il en existe une avec les variables "meta" - qui stipule ce qui suit:
  

meta http-equiv = " Type de contenu " content = " application / xhtml + xml,   text / xml, text / html; charset = utf-8 "

  • Et un autre plus tard, le code qui se lit comme suit:
  

form id = " fpcByAdvancedSearch: fpcSearch " name = " fpcByAdvancedSearch: fpcSearch " méthode = " post " action = & c; / cpotools / apps / fpc / personnel / findByCity? execution = e1s1 " enctype = "application / x-www-form-urlencoded"

Ma question est la suivante: à qui dois-je rester?

Laissez-moi deviner, le premier ContentType doit être considéré comme le second uniquement pour une autre demande à une fonction ou à peu près lorsque les données sont publiées?

  

MODIFIER: Conformément à la demande, la solution la plus proche de moi est répertoriée sous cette question:    WebRequest: Comment trouver un code postal utilisant une requête Web avec ce ContentType = ”application / xhtml + xml, text / xml, text / html; charset = utf-8 ”?

Merci pour toute aide! : -)

Était-ce utile?

La solution

J'essaie de comprendre pourquoi vous n'utilisez pas la classe 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);

Vous pouvez vérifier le codage utilisé par le serveur lors de l'envoi des résultats, s'il utilise UTF-8, remplacez la dernière ligne par: -

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

Certains problèmes que je remarque dans votre code d'origine: -

  1. Le premier champ est précédé de & amp;, cela ne devrait pas être là.
  2. Vous devez utiliser l'appel Uri.EscapeDataString pour chaque valeur de champ.
  3. Vous essayez de construire un flux de mémoire autour du résultat de GetRequestStream , je ne vois pas ce que cela permettrait d'accomplir même si MemoryStream disposait d'un tel constructeur de toute façon. Il suffit d'écrire directement dans le flux renvoyé par GetRequestStream

Si vous l’avez déjà fait, procurez-vous une copie de fiddler pour pouvoir observer ce qui se passe lorsqu'une norme form demande les données avec succès et ce que fait votre code.

Modifier : si vous avez la preuve que l'absence de conteneur de cookies est ce qui empêche WebClient de ne pas fonctionner, vous pouvez essayer cette approche: -

public class MyWebClient : WebClient
{

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

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

Maintenant, utilisez mon code ci-dessus pour instancer plutôt que d'instancier WebClient instance MyWebClient .

Autres conseils

HTTPWebRequest renverra le contenu de l'URL demandée. S'il s'agit d'une page HTML, il renverra un balisage HTML. Si le contenu de la page est XML, il renverra un balisage XML.

Il semble que vous ayez besoin d’un service Web. Je verrais si ce site a des ressources Web disponibles pour traiter ce type de demande. Si tel est le cas, il renverra un balisage XML et JSON en réponse à votre requête. Sinon, il vous reste à analyser la sortie de la requête.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top