Cómo publicar datos en una URL específica usando WebClient en C #

319

Necesito usar "Publicación HTTP" con WebClient para publicar algunos datos en una URL específica que tengo.

Ahora, sé que esto se puede lograr con WebRequest, pero por alguna razón quiero usar WebClient en su lugar. ¿Es eso posible? Si es así, ¿alguien puede mostrarme algún ejemplo o indicarme la dirección correcta?

SolidSnake
fuente

Respuestas:

374

Acabo de encontrar la solución y sí, fue más fácil de lo que pensaba :)

Así que aquí está la solución:

string URI = "http://www.myurl.com/post.php";
string myParameters = "param1=value1&param2=value2&param3=value3";

using (WebClient wc = new WebClient())
{
    wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
    string HtmlResult = wc.UploadString(URI, myParameters);
}

funciona como encanto :)

SolidSnake
fuente
28
Un pequeño truco: es mejor usar un HttpRequestHeader.ContentTypemiembro de enumeración aquí así web.Headers[HttpRequestHeader.ContentType]: p
Alex
12
Otro inconveniente, debe deshacerse del cliente web correctamente utilizando .dispose o el idioma "using": using (WebClient wc = new WebClient ()) {// su código aquí}
Mikey Hogarth
1
@RobinVanPersi Creo que ShikataGanai (Rafik bari) significa que la otra respuesta ( stackoverflow.com/a/13061805/1160796 ) es mejor porque maneja la codificación por usted.
basher
3
@ alpsystems.com Los objetos ID desechables deben ser eliminados adecuadamente por el programador, ya sea envolviéndolos dentro de un uso o invocando explícitamente .Dispose (). Recolector de basura no puede realizar un seguimiento de los recursos no administrados, como controladores de archivos de bases de datos, conexiones y así sucesivamente
ccalboni
1
Para extender la explicación de @ ccalboni. En algunos casos, el recolector de basura limpiará los recursos no administrados y similares llamando al destructor (por ejemplo, WebClienthereda de Component, que contiene ~Component() {Dispose(false);}). El problema es que el recolector de basura puede tomar un tiempo arbitrariamente largo para hacerlo, ya que no tiene en cuenta los recursos no administrados al tomar decisiones de recolección. Los recursos de alto valor deben limpiarse lo antes posible. Por ejemplo, dejar abierto un identificador de archivo innecesario podría impedir que otro código borre o escriba el archivo.
Brian
362

Hay un método incorporado llamado UploadValues que puede enviar HTTP POST (o cualquier tipo de métodos HTTP) Y maneja la construcción del cuerpo de la solicitud (concatenando parámetros con "&" y escapándose caracteres mediante codificación de URL) en el formato de datos de forma adecuado:

using(WebClient client = new WebClient())
{
    var reqparm = new System.Collections.Specialized.NameValueCollection();
    reqparm.Add("param1", "<any> kinds & of = ? strings");
    reqparm.Add("param2", "escaping is already handled");
    byte[] responsebytes = client.UploadValues("http://localhost", "POST", reqparm);
    string responsebody = Encoding.UTF8.GetString(responsebytes);
}
Endy Tjahjono
fuente
1
¿Qué sucede si quiero publicar un modelo en el controlador? ¿Puedo seguir usando reqparm.Add (string, string)?
Burak Karakuş
66
@ BurakKarakuş, ¿quieres decir que quieres enviar JSON en el cuerpo? Entonces es posible que desee utilizar WebClient.UploadString . No olvide agregar Content-Type: application / json en el encabezado.
Endy Tjahjono
@EndyTjahjono: ¿Cómo puedo publicar valores de botones de radio? Suponga que tengo 3 botones de radio que pertenecen al mismo grupo.
Asad Refai
¿Cómo obtengo el código de respuesta? Encabezados de respuesta? ¿Tengo que analizar la respuesta? ¿Hay una manera fácil de hacer eso?
Jay Sullivan el
ADVERTENCIA . namevalueCollection donest permite la misma clave. Esto puede conducir a un comportamiento extraño
bh_earth0
40

Usando WebClient.UploadStringo WebClient.UploadDatapuede enviar datos al servidor fácilmente. Mostraré un ejemplo usando UploadData, ya que UploadString se usa de la misma manera que DownloadString.

byte[] bret = client.UploadData("http://www.website.com/post.php", "POST",
                System.Text.Encoding.ASCII.GetBytes("field1=value1&amp;field2=value2") );

            string sret = System.Text.Encoding.ASCII.GetString(bret);

más: http://www.daveamenta.com/2008-05/c-webclient-usage/

Pranay Rana
fuente
55
mejor usar: client.Encoding = System.Text.UTF8Encoding.UTF8; string varValue = Uri.EscapeDataString (valor);
Yuriy Vikulov
23
string URI = "site.com/mail.php";
using (WebClient client = new WebClient())
{
    System.Collections.Specialized.NameValueCollection postData = 
        new System.Collections.Specialized.NameValueCollection()
       {
              { "to", emailTo },  
              { "subject", currentSubject },
              { "body", currentBody }
       };
    string pagesource = Encoding.UTF8.GetString(client.UploadValues(URI, postData));
}
Andrés
fuente
21
//Making a POST request using WebClient.
Function()
{    
  WebClient wc = new WebClient();

  var URI = new Uri("http://your_uri_goes_here");

  //If any encoding is needed.
  wc.Headers["Content-Type"] = "application/x-www-form-urlencoded";
  //Or any other encoding type.

  //If any key needed

  wc.Headers["KEY"] = "Your_Key_Goes_Here";

  wc.UploadStringCompleted += 
      new UploadStringCompletedEventHandler(wc_UploadStringCompleted);

  wc.UploadStringAsync(URI,"POST","Data_To_Be_sent");    
}

void wc__UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)    
{  
  try            
  {          
     MessageBox.Show(e.Result); 
     //e.result fetches you the response against your POST request.         
  }
  catch(Exception exc)         
  {             
     MessageBox.Show(exc.ToString());            
  }
}
TeJ
fuente
El uso de la versión asíncrona es bueno, todo lo anterior está publicando y bloqueando la ejecución.
Juan
eliminar double __ para arreglar wc__UploadStringCompleted
Joel Davis
1
Todas las respuestas anteriores funcionarán bien en las pruebas, pero en una situación de la vida real con Internet deficiente, esta es una mejor respuesta.
Joel Davis
2

El uso de simple client.UploadString(adress, content);normalmente funciona bien, pero creo que debe recordarse que se WebExceptionlanzará un si no se devuelve un código de estado HTTP exitoso. Usualmente lo manejo así para imprimir cualquier mensaje de excepción que el servidor remoto está devolviendo:

try
{
    postResult = client.UploadString(address, content);
}
catch (WebException ex)
{
    String responseFromServer = ex.Message.ToString() + " ";
    if (ex.Response != null)
    {
        using (WebResponse response = ex.Response)
        {
            Stream dataRs = response.GetResponseStream();
            using (StreamReader reader = new StreamReader(dataRs))
            {
                responseFromServer += reader.ReadToEnd();
                _log.Error("Server Response: " + responseFromServer);
            }
        }
    }
    throw;
}
Ogglas
fuente
Gracias Ogglas. Pasé mucho tiempo para encontrar el error y su código me da más información para corregir.
Kate
1

Usando webapiclient con el modelo, envíe la solicitud de parámetros json de serialización.

PostModel.cs

    public string Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public int Age { get; set; }

WebApiClient.cs

internal class WebApiClient  : IDisposable
  {

    private bool _isDispose;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    public void Dispose(bool disposing)
    {
        if (!_isDispose)
        {

            if (disposing)
            {

            }
        }

        _isDispose = true;
    }

    private void SetHeaderParameters(WebClient client)
    {
        client.Headers.Clear();
        client.Headers.Add("Content-Type", "application/json");
        client.Encoding = Encoding.UTF8;
    }

    public async Task<T> PostJsonWithModelAsync<T>(string address, string data,)
    {
        using (var client = new WebClient())
        {
            SetHeaderParameters(client);
            string result = await client.UploadStringTaskAsync(address, data); //  method:
    //The HTTP method used to send the file to the resource. If null, the default is  POST 
            return JsonConvert.DeserializeObject<T>(result);
        }
    }
}

Método de llamada comercial

    public async Task<ResultDTO> GetResultAsync(PostModel model)
    {
        try
        {
            using (var client = new WebApiClient())
            {
                var serializeModel= JsonConvert.SerializeObject(model);// using Newtonsoft.Json;
                var response = await client.PostJsonWithModelAsync<ResultDTO>("http://www.website.com/api/create", serializeModel);
                return response;
            }
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }

    }
Bora Karaca
fuente
0

Aquí está la respuesta clara:

public String sendSMS(String phone, String token) {
    WebClient webClient = WebClient.create(smsServiceUrl);

    SMSRequest smsRequest = new SMSRequest();
    smsRequest.setMessage(token);
    smsRequest.setPhoneNo(phone);
    smsRequest.setTokenId(smsServiceTokenId);

    Mono<String> response = webClient.post()
          .uri(smsServiceEndpoint)
          .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
          .body(Mono.just(smsRequest), SMSRequest.class)
          .retrieve().bodyToMono(String.class);

    String deliveryResponse = response.block();
    if (deliveryResponse.equalsIgnoreCase("success")) {
      return deliveryResponse;
    }
    return null;
}
KayV
fuente