HttpWebRequest: ¿Cómo encontrar un código postal en Canada Post a través de un WebRequest con x-www-form-adjunto?

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

Pregunta

Actualmente estoy escribiendo algunas pruebas para que pueda mejorar mis habilidades con la interacción de Internet a través de Windows Forms. Una de esas pruebas es encontrar un código postal que debe devolver el sitio web de Canada Post.

  1. Mi configuración de URL predeterminada está establecida en: http: / /www.canadapost.ca/cpotools/apps/fpc/personal/findByCity?execution=e4s1
  2. Los campos de formulario obligatorios son: número de calle , nombre de calle , ciudad , provincia
  3. ContentType es " application / x-www-form-enclosed "
  

EDITAR: considere el valor " application / x-www-form-encoded " en lugar del valor del punto 3 como contentType. (¡Gracias EricLaw-MSFT!)

     

El resultado que obtengo no es el resultado esperado. Obtengo el código fuente HTML de la página donde podría ingresar manualmente la información para encontrar el código postal, pero no el código fuente HTML con el código postal encontrado. ¿Alguna idea de lo que estoy haciendo mal?

     

¿Debo considerar seguir el camino XML? ¿Es posible en primer lugar buscar en Canada Post de forma anónima?

Aquí hay una muestra de código para una mejor descripción:

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

Parece que estoy atrapado en el cuello de una botella en mi punto de vista. No encuentro salida al resultado deseado.

  

EDITAR: parece que tiene que haber parámetros en cuanto al ContentType de este sitio. Déjame explicarte.

  • Hay uno con las '' meta '' -variables que estipula lo siguiente:
  

meta http-equiv = " Tipo de contenido " contenido = " application / xhtml + xml,   texto / xml, texto / html; charset = utf-8 "

  • Y otro más abajo en el código que se lee como:
  

id de formulario = " fpcByAdvancedSearch: fpcSearch " name = " fpcByAdvancedSearch: fpcSearch " método = " publicar " action = " / cpotools / apps / fpc / personal / findByCity? execute = e1s1 " enctype = " application / x-www-form-urlencoded "

Mi pregunta es la siguiente: ¿con cuál debo seguir?

Permítanme adivinar, ¿el primer ContentType debe considerarse ya que el segundo es solo para otra solicitud a una función más o menos cuando se publican los datos?

  

EDITAR: Según la solicitud, más cerca de la solución que estoy aparece en esta pregunta:    WebRequest: Cómo encontrar un código postal usando un WebRequest contra este ContentType = ”application / xhtml + xml, text / xml, text / html; charset = utf-8 "?

¡Gracias por cualquier ayuda! :-)

¿Fue útil?

Solución

Estoy tratando de ver una razón por la que no está utilizando la clase 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);

Es posible que desee verificar la codificación utilizada por el servidor al enviar los resultados, si usa UTF-8 cambie la última línea a: -

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

Algunos problemas que veo en su código original:

  1. El primer campo tiene el prefijo & amp ;, que no debería estar allí.
  2. Necesita usar la llamada Uri.EscapeDataString en cada valor de campo.
  3. Está intentando construir una secuencia de memoria alrededor del resultado de GetRequestStream , no puedo ver qué lograría eso incluso si MemoryStream tuviera un constructor de este tipo, pero no de todos modos. Simplemente escriba directamente en la secuencia devuelta por GetRequestStream

Si ya lo ha hecho, consiga una copia de fiddler para que pueda observar lo que ocurre cuando un estándar formulario solicita los datos correctamente y lo que está haciendo su código.

Editar : si tiene evidencia de que la falta de un contenedor de cookies es lo que hace que WebClient no funcione, entonces puede probar este enfoque: -

public class MyWebClient : WebClient
{

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

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

Ahora use mi código anterior para, pero en su lugar, instan WebClient instancia MyWebClient en su lugar.

Otros consejos

HTTPWebRequest devolverá el contenido de la URL solicitada. Si es una página HTML, devolverá el marcado HTML. Si el contenido de la página es XML, devolverá el marcado XML.

Parece que lo que necesita es un servicio web. Vería si ese sitio tiene algún servicio web disponible para procesar ese tipo de solicitud. Si lo hacen, devolverá el marcado XML, JSON en respuesta a su consulta. De lo contrario, tendrá que analizar el resultado de la solicitud.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top