WebRequest: como encontrar um código postal usando uma feveira web contra este contentType = “Application/xhtml+xml, text/xml, text/html; charset = utf-8 ”?

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

Pergunta

Eu postei isso pela primeira vez: Httpwebrequest: Como encontrar um código postal no Canadá POST através de um WebRequest com X-WWW-Form-Form?.

Seguindo as sugestões de Anthonywjones, mudei meu código após as sugestões dele.

Em uma continuação do meu inquérito, notei com o tempo que o tipo de conteúdo do Canadá é mais provável "Application/xhtml+xml, text/xml, text/html; charset = utf-8".

Minhas perguntas são:

  1. Como fazemos o WebRequest contra um site do tipo conteúdo?
  2. Temos que continuar com o objeto NameValuECollection?
  3. De acordo com Scott Lance, que generosamente me forneceu informações preciosas dentro da minha pergunta anterior, o WebRequest devolverá o tipo de informação que qualquer que seja o tipo de conteúdo, estou perdendo alguma coisa aqui?
  4. Tenho que alterar meu código por causa da alteração do tipo conteúdo?

Aqui está o meu código para que possa ser mais fácil entender meu progresso.

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

Esse código realmente retorna o código -fonte HTML do formulário que se deve preencher com as informações necessárias para processar com a pesquisa de código postal. O que eu desejo é obter o código -fonte HTML ou o que quer que seja com o código postal encontrado.

EDITAR: Aqui está a WebException que recebo agora: "Não é possível enviar um órgão de conteúdo com esse tipo de verbo". (Esta é uma tradução da exceção francesa "Impossible D'Essoyer Un Corps do ConteNu Avec CE Type de Verbe".

Aqui está o meu código:

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

A linha que causa a exceção é apontada com "=>". Parece que não posso usar o Get como método, mas é isso que me foi dito para fazer ...

Alguma ideia do que estou perdendo aqui? Eu tento fazer o que Justin (veja a resposta) me recomendou.

Agradecemos antecipadamente por qualquer ajuda! :-)

Foi útil?

Solução

Como uma introdução ao mundo da escravo da tela, você escolheu um estojo muito difícil! A página de pesquisa do Canada Post funciona como esta:

  1. A primeira página é um formulário que aceita os valores do endereço
  2. Esta página publica em um segundo URL.
  3. Esse segundo URL, por sua vez, redireciona (usando um redirecionamento HTTP 302) para uma terceira URL que realmente mostra a resposta HTML contendo o código postal.

Piorando a situação, a página na etapa nº 3 precisa conhecer o biscoito definido na etapa 1. Então você precisa usar o mesmo CookieContainer para todos os três pedidos (embora possa ser suficiente enviar o mesmo CookieContainer apenas #2 e #3).

Além disso, pode ser necessário enviar cabeçalhos HTTP adicionais nessas solicitações, como aceitar. Suspeito que onde você esteja tendo problemas é que o httpwebrequest por alças padrão redireciona de forma transparente para você- mas quando o redireciona transparentemente, pode não adicionar os cabeçalhos HTTP certos necessários para se passar por um navegador.

A solução é definir o HttpWebRequest's AllowAutoRedirect propriedade para false e lidar com o redirecionamento. Em outras palavras, uma vez que a primeira solicitação retorne um redirecionamento, você precisará retirar o URL no HttpWebResponse's Location: cabeçalho. Então você precisará criar um novo HttpWebRequest (Desta vez, uma solicitação GET regular, não uma postagem) para esse URL. Lembre -se de enviar o mesmo biscoito! (a CookieContainer aula torna isso muito fácil)

Você também pode precisar fazer uma solicitação adicional (nº 1 na minha lista acima) para configurar o cookie da sessão. Se eu fosse você, presumo que isso seja necessário, simplesmente para eliminá -lo como um problema, e tentar remover essa etapa mais tarde e ver se sua solução ainda funciona.

Você vai querer baixar e usar Fiddler (www.fiddlertool.com) para ajudá -lo com tudo isso. O Fiddler permite que você assista às solicitações HTTP passando pelo fio e permite que você (por meio do recurso Builder de solicitações) permite criar solicitações HTTP para que você possa ver quais cabeçalhos são realmente necessários.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top