Pubblica i dati del modulo utilizzando HttpWebRequest


91

Voglio inviare alcuni dati del modulo a un URL specificato che non è all'interno della mia applicazione web. Ha lo stesso dominio, come "domain.client.nl". L'applicazione web ha un URL "web.domain.client.nl" e l'URL in cui voglio postare è "idp.domain.client.nl". Ma il mio codice non fa nulla ..... qualcuno sa cosa sto sbagliando?

Wouter

StringBuilder postData = new StringBuilder();
postData.Append(HttpUtility.UrlEncode(String.Format("username={0}&", uname)));
postData.Append(HttpUtility.UrlEncode(String.Format("password={0}&", pword)));
postData.Append(HttpUtility.UrlEncode(String.Format("url_success={0}&", urlSuccess)));
postData.Append(HttpUtility.UrlEncode(String.Format("url_failed={0}", urlFailed)));

ASCIIEncoding ascii = new ASCIIEncoding();
byte[] postBytes = ascii.GetBytes(postData.ToString());

// set up request object
HttpWebRequest request;
try
{
    request = (HttpWebRequest)HttpWebRequest.Create(WebSiteConstants.UrlIdp);
}
catch (UriFormatException)
{
    request = null;
}
if (request == null)
    throw new ApplicationException("Invalid URL: " + WebSiteConstants.UrlIdp);

request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postBytes.Length;
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";

// add post data to request
Stream postStream = request.GetRequestStream();
postStream.Write(postBytes, 0, postBytes.Length);
postStream.Flush();
postStream.Close();


6
Non proprio un duplicato, come l'altro vuole specificamente usare WebClient.

Risposte:


71

Sia il nome del campo che il valore devono essere codificati nell'URL. formato dei dati del post e stringa di query sono gli stessi

Il modo di fare .net è qualcosa del genere

NameValueCollection outgoingQueryString = HttpUtility.ParseQueryString(String.Empty);
outgoingQueryString.Add("field1","value1");
outgoingQueryString.Add("field2", "value2");
string postdata = outgoingQueryString.ToString();

Questo si occuperà della codifica dei campi e dei nomi dei valori


10
string postdata = outgoingQueryString.ToString();ti darà una stringa con il valore "System.Collections.Specialized.NameValueCollection".
— sfuqua

1
In realtà @sfuqua se decompili il sorgente per HttpUtility (in particolare quello in System.Web) vedrai che restituisce un tipo NameValueCollection specializzato: return (NameValueCollection) new HttpValueCollection (query, false, true, encoding); che converte correttamente la raccolta in una stringa di query. Se usi quello di RestSharp, tuttavia, non ...
— The Senator

Interessante, poiché avevo visto questo problema esatto ToString(), anche se ora non ricordo se fosse durante l'utilizzo di RestSharp. Possibilità definitiva. Grazie per la correzione.
— sfuqua

Non è stato immediatamente chiaro come outgoingQueryStringfunzionasse come implicito nel codice di esempio. Queste due domande rispondono a: (1) HttpValueCollection e NameValueCollection e (2) Qualsiasi classe .NET che crea una stringa di query con coppie di valori chiave o simili .
— Kenny Evitt

56

Prova questo:

var request = (HttpWebRequest)WebRequest.Create("http://www.example.com/recepticle.aspx");

var postData = "thing1=hello";
    postData += "&thing2=world";
var data = Encoding.ASCII.GetBytes(postData);

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

using (var stream = request.GetRequestStream())
{
    stream.Write(data, 0, data.Length);
}

var response = (HttpWebResponse)request.GetResponse();

var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();

6
Preferirei scrivere: request.Method = WebRequestMethods.Http.Post;
— Totalys

richiesta di controllo Risposta prima dell'uso
— Marco Fantasia

@MarcoFantasia Se controlli request.HaveResponsedevi prima ottenere effettivamente la risposta. HttpWebResponse response = (HttpWebResponse) request.GetResponse(); if (request.HaveResponse) { ... }
— Sì Barry

40

Stai codificando il modulo in modo errato. Dovresti codificare solo i valori:

StringBuilder postData = new StringBuilder();
postData.Append("username=" + HttpUtility.UrlEncode(uname) + "&");
postData.Append("password=" + HttpUtility.UrlEncode(pword) + "&");
postData.Append("url_success=" + HttpUtility.UrlEncode(urlSuccess) + "&");
postData.Append("url_failed=" + HttpUtility.UrlEncode(urlFailed));

modificare

Ho sbagliato. Secondo la sezione 8.2.1 RFC1866 sia i nomi che i valori dovrebbero essere codificati.

Ma per l'esempio dato, i nomi non hanno caratteri che devono essere codificati, quindi in questo caso il mio esempio di codice è corretto;)

Il codice nella domanda è ancora errato in quanto codificherebbe il segno di uguale che è il motivo per cui il server web non può decodificarlo.

Un modo più corretto sarebbe stato:

StringBuilder postData = new StringBuilder();
postData.AppendUrlEncoded("username", uname);
postData.AppendUrlEncoded("password", pword);
postData.AppendUrlEncoded("url_success", urlSuccess);
postData.AppendUrlEncoded("url_failed", urlFailed);

//in an extension class
public static void AppendUrlEncoded(this StringBuilder sb, string name, string value)
{
    if (sb.Length != 0)
        sb.Append("&");
    sb.Append(HttpUtility.UrlEncode(name));
    sb.Append("=");
    sb.Append(HttpUtility.UrlEncode(value));
}

Grazie, ma ora ricevo il seguente errore: Il server remoto ha restituito un errore: (412) Precondizione non riuscita.
— wsplinter

Io google molto :) Ma l'ho risolto, lo sto facendo in modo sporco. Non faccio una HttpWebRequest ma costruisco un form html all'interno di una String e lo scrivo al browser (nell'onload farò un submit).
— wsplinter

3
@wsplinter: aiuterebbe gli altri se si documentasse la soluzione alla precondizione fallita.
— jgauffin

@jgauffin: come inserisco i valori dei pulsanti di opzione? Supponiamo che io abbia 3 pulsanti di opzione appartenenti allo stesso gruppo.
— Asad Refai

1
Apparentemente, questo non ha funzionato per me abbastanza come previsto poiché UrlEncode cambia simboli come @ in un codice che non veniva accettato nella chiamata API; cambiandolo per utilizzare NameValueCollection come mostrato nella risposta di @ user3389691 funziona perfettamente.
— dhruvpatel
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.