2009-11-01 7 views
9

Quindi sto provando a POST qualcosa su un server web.C# HttpWebRequest POST'ing falling

System.Net.HttpWebRequest EventReq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create("url"); 
System.String Content = "id=" + Id; 
EventReq.ContentLength = System.Text.Encoding.UTF8.GetByteCount(Content); 
EventReq.Method = "POST"; 
EventReq.ContentType = "application/x-www-form-urlencoded"; 
System.IO.StreamWriter sw = new System.IO.StreamWriter(EventReq.GetRequestStream(), System.Text.Encoding.UTF8); 
sw.Write(Content); 
sw.Flush(); 
sw.Close(); 

Sembra a posto, sto impostando content-length in base alle dimensioni dei dati codificati ... In ogni caso non riesce a sw.flush() con "byte da scrivere al flusso di superare il Content -Dimensione lunghezza specificata "

StreamWriter sta facendo un po 'di magia dietro la schiena di cui non sono a conoscenza? C'è un modo in cui posso osservare ciò che StreamWriter sta facendo?

risposta

24

Altre risposte hanno spiegato come evitare questo, ma ho pensato di rispondere perché sta accadendo: si finisce con uno byte order mark prima del contenuto effettivo.

È possibile evitare questo chiamando new UTF8Encoding(false) invece di utilizzare Encoding.UTF8. Ecco un breve programma per dimostrare la differenza:

using System; 
using System.Text; 
using System.IO; 

class Test  
{ 
    static void Main() 
    { 
     Encoding enc = new UTF8Encoding(false); // Prints 1 1 
     // Encoding enc = Encoding.UTF8; // Prints 1 4 
     string content = "x"; 
     Console.WriteLine(enc.GetByteCount("x")); 
     MemoryStream ms = new MemoryStream(); 
     StreamWriter sw = new StreamWriter(ms, enc); 
     sw.Write(content); 
     sw.Flush(); 
     Console.WriteLine(ms.Length); 
    } 

} 
+0

Buon posto. Ho pensato * di scavare, ma ...

+0

Lei signore è corretto :) Spiega quell'osservazione su \ 357 \ 273 \ 277 da wirehark che ho fatto nell'altro commento. Mille grazie! –

4

magari fare come più facile:

using(WebClient client = new WebClient()) { 
    NameValueCollection values = new NameValueCollection(); 
    values.Add("id",Id); 
    byte[] resp = client.UploadValues("url","POST", values); 
} 

o vedere here per una discussione che permette l'uso come:

client.Post(destUri, new { 
    id = Id // other values here 
}); 
3

Non è necessario impostare ContentLength esplicitamente, dal momento che verrà impostato automaticamente alle dimensioni del dati scritti per richiedere il flusso quando lo chiudi.

+0

Sei proprio corretto; questo risolve quel particolare problema. Ma usando Wireshark per guardare il pacchetto che viene inviato, StreamWriter sta anteponendo qualcosa ai dati POST ... \ 357 \ 273 \ 277id = 301Rbu Dove sono quei 3 byte provenienti da ??? Content-Length è impostato su 12 in questo pacchetto. –

+2

@Jon Skeet lo ha descritto bene (come al solito =)) - questo è il cosiddetto 'Unicode byte order mark' che identifica se il testo è UTF-8, UTF-16 Big-endian, UTF-16 Little-endian ecc. Maggiori informazioni qui http://en.wikipedia.org/wiki/Byte-order_mark –