HttpWebRequest: Come trovare un codice postale su Canada Post tramite un WebRequest con x-www-form-enclosure?

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

Domanda

Attualmente sto scrivendo alcuni test in modo da poter migliorare le mie capacità con l'interazione Internet tramite Windows Forms. Uno di questi test è trovare un codice postale che dovrebbe essere restituito dal sito web di Canada Post.

  1. La mia impostazione URL predefinita è impostata su: http: / /www.canadapost.ca/cpotools/apps/fpc/personal/findByCity?execution=e4s1
  2. I campi del modulo richiesti sono: streetNumber , streetName , città , provincia
  3. Il contentType è " application / x-www-form-enclosure "
  

MODIFICA: considera il valore " application / x-www-form-coded " anziché il valore del punto 3 come contentType. (Grazie EricLaw-MSFT!)

     

Il risultato che ottengo non è il risultato previsto. Ottengo il codice sorgente HTML della pagina dove posso inserire manualmente le informazioni per trovare il codice postale, ma non il codice sorgente HTML con il codice postale trovato. Hai idea di cosa sto facendo di sbagliato?

     

Prenderò in considerazione l'idea di utilizzare XML? È innanzitutto possibile cercare su Canada Post in modo anonimo?

Ecco un esempio di codice per una migliore descrizione:

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

Mi sembra bloccato nel collo di una bottiglia dal mio punto di vista. Non trovo alcuna via d'uscita per il risultato desiderato.

  

MODIFICA: Sembra che ci siano parametri per quanto riguarda il ContentType di questo sito. Lasciami spiegare.

  • Ce n'è uno con le variabili "quot" e "che stabilisce quanto segue:
  

meta http-equiv = " Tipo di contenuto " content = " application / xhtml + xml,   text / xml, text / html; charset = utf-8 "

  • E un altro dopo il codice letto come:
  

form id = " fpcByAdvancedSearch: fpcSearch " name = " fpcByAdvancedSearch: fpcSearch " method = " postale " action = " / cpotools / applicazioni / FPC / personale / findByCity esecuzione = e1s1 " enctype = " application / x-www-form-urlencoded "

La mia domanda è la seguente: con quale devo restare?

Fammi indovinare, il primo ContentType deve essere considerato come il secondo è solo per un'altra richiesta a una funzione o giù di lì quando i dati vengono pubblicati?

  

MODIFICA: Come da richiesta, il più vicino alla soluzione che sono è elencato sotto questa domanda:    WebRequest: come trovare un codice postale che utilizza una richiesta Web contro questo ContentType = "application / xhtml + xml, text / xml, text / html; charset = utf-8” ?

Grazie per l'aiuto! : -)

È stato utile?

Soluzione

Sto cercando di vedere un motivo per cui non stai usando 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);

Potresti voler controllare la codifica utilizzata dal server quando invia i risultati, se usa UTF-8 cambia l'ultima riga in: -

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

Alcuni problemi che rilevo nel tuo codice originale: -

  1. Il primo campo ha il prefisso & amp ;, che non dovrebbe essere lì.
  2. È necessario chiamare Uri.EscapeDataString su ciascun valore di campo.
  3. Stai tentando di costruire un flusso di memoria attorno al risultato di GetRequestStream , non riesco a vedere cosa raggiungerebbe anche se MemoryStream avesse un tale costruttore ma non lo fa comunque. Basta scrivere direttamente nello stream restituito da GetRequestStream

Se lo hai già fatto procurati una copia di fiddler in modo da poter osservare cosa succede quando uno standard form richiede i dati correttamente e cosa sta facendo il tuo codice.

Modifica : se hai prove che la mancanza di un contenitore di cookie è ciò che impedisce a WebClient di non funzionare, puoi provare questo approccio: -

public class MyWebClient : WebClient
{

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

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

Ora usa il mio codice sopra per invece invece istanziare WebClient istanza MyWebClient .

Altri suggerimenti

HTTPWebRequest restituirà il contenuto dell'URL richiesto. Se è una pagina HTML, restituirà markup HTML. Se il contenuto della pagina è XML, verrà restituito il markup XML.

Sembra che tu abbia bisogno di un Webservice. Vorrei vedere se quel sito ha qualche webseriv disponibile per elaborare quel tipo di richiesta. In tal caso, restituirà XML, markup JSON in risposta alla tua query. Altrimenti, ti verrà permesso di analizzare l'output della richiesta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top