applicationx-www-form-urlencoded with HttpWebRequest

5

I am making a system to authenticate the Token (derived from the credit card) next to Cielo. This token has special characters like +

Cielo receives the data via XML. I made the following code to send:

 private String sendHttpRequest(String message)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endpoint);

    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";

    using (Stream stream = request.GetRequestStream())
    {
        UTF8Encoding encoding = new UTF8Encoding();
        byte[] bytes = encoding.GetBytes("mensagem=" + message);

        stream.Write(bytes, 0, bytes.Length);
    }


    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    string result;

    using (Stream stream = response.GetResponseStream())
    {
        using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
        {
            result = reader.ReadToEnd();
        }
    }

    return result.ToString();
}

But the token arrives in a different way in Cielo returning me Token not found, being the one that generated the Token. When contacting the support of why are their response:

  

The error occurs when sending the token request without the conversion of   URL-encoding, that is, special characters (as an example +) is   interpreted as spaces by the platform. This is because   platform receives the XML in a parameter of the HTTP request, using   the content-type applicationx-www-form-urlencoded. Technologies like Java   (Apache HttpComponentHttpClient) perform this conversion   automatically, becoming transparent to the developer. O   establishment must evaluate and adjust the encoding (URLEncode) in its   otherwise, other special characters will   same problem.

I think my code is correct when reading this url tried to do something with HttpUtility.UrlEncode (message); ex:

var t = HttpUtility.UrlEncode(message);
byte[] bytes = encoding.GetBytes ("mensagem=" + t);

But the same mistake, before I call there and complain to Cielo would like some help, because I may be commenting some mistake.

Is there any way I can copy the Bytes and try to simulate this post by some plugin from my browser? What do I do with the Chrome REST Client plugin?

How can I debug and visualize something I can help?

NOTE: When the token is without these special characters, the same code above works perfectly.

    
asked by anonymous 05.04.2016 / 18:20

2 answers

1

Would not it be just the case of escaping the Token characters ?

var tokenEscapado = Uri.EscapeDataString(token);

HttpUtility.UrlEncode will not work because it is for URL's, and what is giving problem is a component in the content of the message, which in this case is XML.

    
13.05.2016 / 22:29
4

Dorathoto, initially I can not see a problem with your code, what I suggest is that you try to make this request using the WebAPI Client.

Install the following package:

Microsoft ASP.NET Web API 2.2 Client >

Then you can use the following code:

private async Task<string> sendHttpRequest(string message)
{
    var data = new Dictionary<string, string>();
    data.Add("mensagem", message);

    using (var cliente = new HttpClient())
    {
        using (var conteudo = new FormUrlEncodedContent(data))
        {
            conteudo.Headers.Clear();
            conteudo.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

            var response = await cliente.PostAsync("minha url", conteudo);
            return await response.Content.ReadAsAsync<string>();
        }
    }
}

You can also use StringContent instead of FormUrlEncodedContent , if you need to set a Encode other than ISO-8859-1 :

private async Task<string> sendHttpRequest(string mensagem)
{
    var data = new Dictionary<string, string>();
    data.Add("mensagem", mensagem);

    using (var cliente = new HttpClient())
    {
        var chaves = new string[data.Count];
        var itens = new string[data.Count];

        data.Keys.CopyTo(chaves, 0);
        for (var indice = 0; indice < itens.Length; indice++)
        {
            var chave = chaves[indice];
            itens[indice] = chave + '=' + data[chave];
        }

        var encoded = Uri.EscapeDataString(String.Join("&", itens)).Replace("%20", "+");
        using (var conteudo = new StringContent(encoded, Encoding.UTF8, "application/x-www-form-urlencoded"))
        {
            var response = await cliente.PostAsync("minha url", conteudo);
            return await response.Content.ReadAsAsync<string>();
        }
    }
}

then you can call this method as follows:

var mensagem = "Hello Wolrd";
var response = Task.Run<string>(async () => await sendHttpRequest(mensagem)).Result;

Another alternative would be to try to use StreamWriter instead of writing directly to Stream of your request

Replace your code snippet similar to the one below:

using (Stream stream = request.GetRequestStream ()) {
    UTF8Encoding encoding = new UTF8Encoding ();
    byte[] bytes = encoding.GetBytes ("mensagem=" + message);
    stream.Write (bytes, 0, bytes.Length);
}

by the following code:

using (var stream = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.UTF8))
{
    var encoded = HttpUtility.UrlEncode("mensagem=" + message)
    stream.Write(encoded);
    stream.Close();
}

You can also try to use other encode types instead of System.Text.Encoding.UTF8 , such as System.Text.Encoding.ASCII

    
05.04.2016 / 18:48