2009-11-01 15 views
9

Próbuję więc POST coś na serwerze internetowym.C# HttpWebRequest POST'ing failing

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(); 

Wygląda w porządku, jestem ustawienie Content-Length na podstawie rozmiaru danych zakodowane ... W każdym razie nie jest on w sw.flush() z „bajtów do zapisania strumienia przekraczać zawartość -Długość rozmiaru określona "

Czy StreamWriter robi trochę magii za moimi plecami, o czym nie wiem? Czy istnieje sposób, w jaki mogę sprawdzić, co robi StreamWriter?

Odpowiedz

24

Inne odpowiedzi wyjaśniły, jak tego uniknąć, ale pomyślałem, że odpowiem, dlaczego tak się dzieje: kończysz z byte order mark przed rzeczywistą treścią.

Można tego uniknąć, dzwoniąc pod numer new UTF8Encoding(false) zamiast za pomocą Encoding.UTF8. Oto krótki program, który pokazuje różnicę:

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

Dobre miejsce. Ja * myślałem * o kopaniu, ale ...

+0

Pan ma rację :) Wyjaśnia, że ​​spostrzeżenie o \ 357 \ 273 \ 277 z wireshark zrobiłem w drugim komentarzu. Wielkie dzięki! –

4

Może zrobić jak łatwiejszego:

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

Albo zobaczyć here do dyskusji umożliwiającej wykorzystanie takich jak:

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

Nie musisz ustawić ContentLength wyraźnie, ponieważ zostanie on automatycznie do rozmiaru dane zapisane do żądania strumienia po jego zamknięciu.

+0

Naprawdę jesteś poprawny; to rozwiązuje ten konkretny problem. Ale użycie Wiresharka do obejrzenia pakietu, który zostanie wysłany, pokazuje, że StreamWriter przygotowuje coś do danych POST ... \ 357 \ 273 \ 277id = 301Rbu Skąd pochodzą te 3 bajty? Długość zawartości jest ustawiona na 12 w tym pakiecie. –

+2

@Jon Skeet opisał to dobrze (jak zwykle =)) - jest to tak zwany "znak rzędu bajtów Unicode", który określa, czy tekst jest UTF-8, UTF-16 Big-endian, UTF-16 Little-endian itp. Czytaj więcej tutaj http://en.wikipedia.org/wiki/Byte-order_mark –