2009-12-14 6 views
3

Я пытаюсь сделать Http POST на веб-сервере Apache.C# - HttpWebRequest - POST

Я обнаружил, что для выполнения запроса требуется настройка ContentLength.

Я бы предпочел создать XmlWriter непосредственно из GetRequestStream() и установить SendChunked в true, но при этом зависает бесконечный запрос.

Вот как создается мой запрос:

private HttpWebRequest MakeRequest(string url, string method) 
    { 
     HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest; 
     request.Method = method; 
     request.Timeout = Timeout; //Property in my class, assume it's 10000 
     request.ContentType = "text/xml"; //I am only writing xml with XmlWriter 
     if (method != WebRequestMethods.Http.Get) 
     { 
      request.SendChunked = true; 
     } 
     return request; 
    } 

Как я могу сделать SendChunked работу, поэтому я не придется устанавливать ContentLength? Я не вижу причины хранить строку XmlWriter где-то, прежде чем отправлять ее на сервер.

EDIT: Вот мой код вызывает проблему:

using (Stream stream = webRequest.GetRequestStream()) 
    { 
     using (XmlWriter writer = XmlWriter.Create(stream, XmlTags.Settings)) 
     { 
      Generator.WriteXml<TRequest>(request, writer); 
     } 
    } 

Перед тем, как не было, используя на объекте поток возвращается из GetRequestStream(), я предположил, XmlWriter закрыли поток при их удалении, но это не тот случай.

Один из ответов ниже, позвольте мне. Я буду отмечать их как ответ.

Что касается HttpWebRequest, то мой оригинальный код работает отлично.

+0

ли работа против другого веб-сервера (не Apache)? И вы закрываете поток через XmlWriter или RequestStream? –

+0

У меня нет сервера Windows, чтобы попробовать его, и мне пришлось потратить время на создание кода на C#, чтобы прочитать сообщение. Мне кажется, что настройка HttpWebRequest должна быть исправлена. – jonathanpeppers

ответ

3

Это должно работать так, как вы его написали. Можем ли мы увидеть код, который фактически выполняет загрузку? Вы помните, чтобы закрыть поток?

+0

My XmlWriter находится в используемом блоке, и он просто записывает некоторые элементы и атрибуты с некоторым циклом. Он вызывает WriteEndDocument для завершения документа. Я начинаю задаваться вопросом, является ли это сервером, а не .NET, но у меня нет сервера Windows для тестирования, хотя версия Apache довольно новая. – jonathanpeppers

+0

'WriteEndDocument' фактически не закрывает поток. Где-то в вашем коде вы вызываете 'GetRequestStream' (или' BeginGetRequestStream'); как только вы закончите писать свой XML, вам нужно вызвать метод «Закрыть» на этом экземпляре 'Stream'.Если вы этого не сделаете, он не узнает, когда вы закончите загрузку, и соединение будет оставаться открытым навсегда. – Aaronaught

+0

Вы используете '' XmlWriter'', который будет располагать 'XmlWriter' и только' XmlWriter'. Это ** Stream **, который вам нужно вызвать 'Dispose' on (или' Close', который является рекомендуемым методом). 'XmlWriter' не сделает этого для вас. – Aaronaught

1

Если посмотреть на пример в http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.sendchunked.aspx, они по-прежнему устанавливают длину содержимого. В самом деле, суть в том, что если вы отправляете данные, вам нужно сообщить получателю, сколько данных вы будете отправлять. Почему вы не знаете, сколько данных вы отправляете, прежде чем отправлять запрос?

ContentLength:

Свойство Значение Тип:. System .. :: Int64 число байтов данных для передачи интернет-ресурса. По умолчанию используется значение -1, которое указывает, что свойство не было установлено и что нет данных запроса для отправки.

Редактировать Аарона (я был неправ):

HttpWebRequest httpWebRequest = HttpWebRequest.Create("http://test") as HttpWebRequest; 
httpWebRequest.SendChunked = true; 
MessageBox.Show("|" + httpWebRequest.TransferEncoding + "|"); 

От System.Net.HttpWebRequest.SerializeHeaders():

if (this.HttpWriteMode == HttpWriteMode.Chunked) 
{ 
    this._HttpRequestHeaders.AddInternal("Transfer-Encoding", "chunked"); 
} 
else if (this.ContentLength >= 0L) 
{ 
    this._HttpRequestHeaders.ChangeInternal("Content-Length", this._ContentLength.ToString(NumberFormatInfo.InvariantInfo)); 
} 
+0

Это нарушит спецификацию HTTP 1.1. Это явно не задокументировано, но вам определенно не нужно устанавливать свойство ContentLength, когда вы используете 'SendChunked = true'. Одна настройка заменяет другую. – Aaronaught

+0

http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 «Если сообщение получено как с полем заголовка Transfer-Encoding, так и с полем заголовка Content-Length, последний ДОЛЖЕН быть проигнорированным ». Так что это разрешено в соответствии с RFC, но это не значит, что оно поддерживается приложением, получающим POST. Простым способом является получение длины и установка его, но какое удовольствие это будет :) Всегда интересно исследовать оптимизированные решения. –

+0

Ну, приложение, получающее POST, это Apache, как указано в исходном вопросе. Если это не очень-очень старая версия Apache, она будет поддерживать кодирование с чередованием. – Aaronaught