Simulando um post HTTP em ASP.NET

Veja nesse artigo como simular um post HTTP através do framework .NET, podendo simular além do envio de parâmetros normais, o envio de parâmetros do tipo file gerados pelo elemento input do HTML. Para que isso seja possível, será apresentada a c

Há alguns dias atrás me deparei com um problema, eu precisava simular um post HTTP de uma pagina HTML. A princípio parecia ser uma tarefa fácil, porém, a página tinha um elemento input, o qual permitia ao usuário selecionar um arquivo e isso acabou complicando um pouco as coisas. Nesse artigo vou mostrar a solução que encontrei, para quem tenha o mesmo problema possa usar como referência.

Após muitas buscar na Internet descobri que um elemento do tipo input do HTML gera uma parâmetro diferente no post, passando o nome e o conteúdo do arquivo. A partir disso utilizei um sniffer para capturar todos os dados do post, e com essas informações desenvolvi a classe HttpPost, como mostra a Listagem 1.

Listagem 1: Classe HttpPost

public class HttpPost { private String _url = String.Empty; private List< HttpPostParameter> _parameters = new List< HttpPostParameter>(); public HttpPost(String url) { this._url = url; } private void AddParameter(HttpPostParameter parameter) { this._parameters.Add(parameter); } public void AddKey(String name, String value) { HttpPostParameter parameter = new HttpPostParameter { Name = name, Value = value, Kind = HttpPostParameterKind.Key }; this.AddParameter(parameter); } public void AddFile(String name, String value) { HttpPostParameter parameter = new HttpPostParameter { Name = name, Value = value, Kind = HttpPostParameterKind.File }; this.AddParameter(parameter); } private List< HttpPostParameter> GetKeys() { return _parameters.FindAll(p => p.Kind == HttpPostParameterKind.Key); } public List< HttpPostParameter> GetFiles() { return _parameters.FindAll(p => p.Kind == HttpPostParameterKind.File); } public String Submit() { String boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x"); HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(this._url); httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary; httpWebRequest.Method = "POST"; httpWebRequest.KeepAlive = true; httpWebRequest.Credentials = System.Net.CredentialCache.DefaultCredentials; Stream memStream = new System.IO.MemoryStream(); Byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); String formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"\";\r\n\r\n"; foreach (HttpPostParameter key in this.GetKeys()) { String formitem = String.Format(formdataTemplate, key.Name, key.Value); Byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); memStream.Write(formitembytes, 0, formitembytes.Length); } memStream.Write(boundarybytes, 0, boundarybytes.Length); String headerTemplate = "Content-Disposition: form-data; name=\"\"; filename=\"\"\r\n Content-Type: plain/text\r\n\r\n"; foreach (HttpPostParameter file in this.GetFiles()) { String header = String.Format(headerTemplate, file.Name, DateTime.Now.ToString("ddMMyyyyTHHmmss")); Byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); memStream.Write(headerbytes, 0, headerbytes.Length); MemoryStream memoryStream = new MemoryStream(Encoding.Default.GetBytes(file.Value)); Byte[] buffer = new Byte[1024]; int bytesRead = 0; while ((bytesRead = memoryStream.Read(buffer, 0, buffer.Length)) != 0) { memStream.Write(buffer, 0, bytesRead); } memStream.Write(boundarybytes, 0, boundarybytes.Length); memoryStream.Close(); } httpWebRequest.ContentLength = memStream.Length; Stream requestStream = httpWebRequest.GetRequestStream(); memStream.Position = 0; byte[] tempBuffer = new byte[memStream.Length]; memStream.Read(tempBuffer, 0, tempBuffer.Length); memStream.Close(); requestStream.Write(tempBuffer, 0, tempBuffer.Length); requestStream.Close(); WebResponse webResponse = httpWebRequest.GetResponse(); Stream stream = webResponse.GetResponseStream(); StreamReader reader = new StreamReader(stream, Encoding.Default); String result = reader.ReadToEnd(); webResponse.Close(); httpWebRequest = null; webResponse = null; return result; } }

Criei também a classe HttpPostParameter (Listagem 2) para representar um parâmetro do post, e o enum HttpPostParameterKind (Listagem 3) que define se o parâmetro é um parâmetro normal ou um arquivo.

Listagem 2: Classe HttpPostParameter

public class HttpPostParameter { public String Name; public String Value; public HttpPostParameterKind Kind; }

Listagem 3: Enum HttpPostParameterKind

public enum HttpPostParameterKind { Key, File }

Não estarei entrando em detalhes na implementação da classe HttpPost, mas vou mostrar como utilizar esta classe. Como podemos ver na listagem 4, a primeira coisa que precisamos fazer é instanciar uma classe, e nisso informar qual a URL que será utilizada para o post. Depois de criado o nosso objeto, podemos adicionar parâmetros através dos métodos AddKey(String, String) para parâmetros normais, e AddFile(String, String) para parâmetros do tipo arquivo. Após determinarmos os parâmetros devemos utilizar o método Submit() para fazer a simulação do post, esse método retorna uma String que nada mais é que o HTML gerado como resposta pelo post, ou seja, o HTML que seria desenhado no browser. Vejamos então na listagem 4 a utilização da classe HttpPost.

Listagem 4: Utilização da classe HttpPost

public static class Main { public static void Main(String [] args) { HttpPost httpPost = new HttpPost("https://www.devmedia.com.br/someservice") httpPost.AddKey("user", "devmain"); httpPost.AddKey("password", "1234"); httpPost.AddFile("fileName.txt", "content"); String htmlResponse = httpPost.Submit(); } }

E é isso pessoal, espero que esse post possa ajudá-los, estou à disposição para qualquer duvida. Um abraço e até a próxima.

Ebook exclusivo
Dê um upgrade no início da sua jornada. Crie sua conta grátis e baixe o e-book

Artigos relacionados