2009-12-14 41 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