2009-12-14 40 views
3

我試圖做一個Http POST到Apache Web服務器。C# - HttpWebRequest - POST

我發現設置ContentLength似乎是工作請求所必需的。

我寧願直接從GetRequestStream()創建一個XmlWriter,並將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的字符串存儲在某個地方的原因。

編輯:這裏是我的代碼導致了問題:

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

之前我做了一個使用Stream對象從GetRequestStream()返回沒有,我以爲處置時的XmlWriter關閉了流,但這不是這樣。

下面的答案之一,讓我來這個。我會將它們標記爲答案。

就HttpWebRequest而言,我的原始代碼工作得很好。

+0

是否對另一個網站服務器工作(而不是Apache)?你是否通過XmlWriter或RequestStream關閉了你的流? – 2009-12-14 18:22:24

+0

我沒有一個Windows服務器來嘗試,我不得不花時間編寫一些C#代碼來閱讀帖子。我覺得像調整HttpWebRequest上的設置應該解決這個問題。 – jonathanpeppers 2009-12-14 19:36:34

回答

3

這應該按照你寫的方式工作。我們可以看到實際上傳的代碼嗎?你記得關閉流嗎?

+0

我的XmlWriter在一個使用塊中,它只是用一些循環編寫一些元素和屬性。它調用WriteEndDocument來結束文檔。我開始懷疑它是否是服務器,而不是.Net,但我沒有一個Windows服務器來測試,儘管Apache的版本很新。 – jonathanpeppers 2009-12-14 19:32:29

+0

'WriteEndDocument'實際上並不關閉流。在你的代碼中的某處,你正在調用'GetRequestStream'(或'BeginGetRequestStream');一旦你完成了你的XML的編寫,你需要在'Stream'實例上調用'Close'方法。如果你沒有,它不會知道你什麼時候完成上傳,連接將永遠持續開放。 – Aaronaught 2009-12-14 20:03:42

+0

您正在使用'XmlWriter',它將處理'XmlWriter'和僅''XmlWriter'。它是** Stream **,你需要調用Dispose(或者Close,這是推薦的方法)。 'XmlWriter'不會爲你做這個。 – Aaronaught 2009-12-14 21:17:24

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規範。它沒有清楚的記錄,但是當你使用'SendChunked = true'時,你肯定不需要設置ContentLength屬性。一個設置替換另一個。 – Aaronaught 2009-12-14 18:38:36

+0

http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 「如果同時收到一個Transfer-Encoding標題字段和一個Content-Length標題字段,則後者必須被忽略。「 所以根據RFC允許它,但並不意味着它是由接收POST的應用程序支持的。 簡單的方法是獲得長度並設置它,但是會有多好玩:)探索優化解決方案總是很有趣。 – 2009-12-14 18:44:36

+0

那麼,如原始問題所述,接收POST的應用程序就是Apache。除非它是一個非常非常舊的Apache版本,否則它將支持分塊編碼。 – Aaronaught 2009-12-14 18:50:19