2009-11-01 5 views
9

Так что я пытаюсь ПОЧТИ что-то на веб-сервере.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(); 

Выглядит хорошо, я уверен, Настройка контента длины в зависимости от размера закодированных данных ... Во всяком случае она не в sw.flush() с «байт, которые будут записаны в поток превышает содержание -Length size "

Is StreamWriter делает магию за моей спиной, о которой я не знаю? Есть ли способ, которым я могу понять, что делает StreamWriter?

ответ

24

Другие ответы объяснили, как избежать этого, но я подумал, что я бы ответил, почему это происходит: у вас заканчивается byte order mark перед вашим фактическим контентом.

Вы можете избежать этого, позвонив по телефону new UTF8Encoding(false) вместо Encoding.UTF8. Вот короткая программа, демонстрирующая разницу:

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

Хорошее место. Я * думал * о копании, но ...

+0

Вы сэр правильно :) Объясняет это наблюдение о \ 357 \ 273 \ 277 из проводов, сделанных мной в другом комментарии. Большое спасибо! –

4

Может быть, сделать как проще:

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

Или увидеть here для обсуждения, позволяющего использовать как:

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

Вам не нужно устанавливать ContentLength явно, так как она будет установлена ​​автоматически по размеру данные, написанные для запроса потока при его закрытии.

+0

Вы действительно правы; это фиксирует эту конкретную проблему. Но использование Wireshark для просмотра отправляемого пакета показывает, что StreamWriter что-то добавляет к данным POST ... \ 357 \ 273 \ 277id = 301Rbu Где находятся эти 3 байта? В этом пакете Content-Length установлено значение 12. –

+2

@ Jon Skeet описал это хорошо (как обычно =)) - это так называемая «Unicode byte-order mark», которая идентифицирует, является ли текст UTF-8, UTF-16 Big-endian, UTF-16 Little-endian и т. Д. Подробнее здесь http://en.wikipedia.org/wiki/Byte-order_mark –