简体   繁体   English

C# - HttpWebRequest - POST

[英]C# - HttpWebRequest - POST

I am trying to make an Http POST to an Apache web server.我正在尝试向 Apache Web 服务器发送 Http POST。

I am finding that setting ContentLength seems to be required for the request to work.我发现该请求似乎需要设置 ContentLength 才能工作。

I would rather create an XmlWriter directly from GetRequestStream() and set SendChunked to true, but the request hangs indefinitely when doing so.我宁愿直接从 GetRequestStream() 创建一个 XmlWriter 并将 SendChunked 设置为 true,但这样做时请求会无限期挂起。

Here is how my request is created:这是我的请求是如何创建的:

    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;
    }

How can I make SendChunked work so I do not have to set ContentLength?我怎样才能让 SendChunked 工作,这样我就不必设置 ContentLength? I do not see a reason to store the XmlWriter's string somewhere before sending it to the server.我看不出有理由在将 XmlWriter 的字符串发送到服务器之前将其存储在某处。

EDIT: Here is my code causing the problem:编辑:这是我的代码导致问题:

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

Before I did not have a using on the Stream object returned from GetRequestStream(), I assumed XmlWriter closed the stream when disposed, but this is not the case.在我没有使用从 GetRequestStream() 返回的 Stream 对象之前,我假设 XmlWriter 在处理时关闭了流,但事实并非如此。

One of the answers below, let me to this.下面的答案之一,让我来回答这个问题。 I'll mark them as the answer.我会将它们标记为答案。

As far as HttpWebRequest is concerned, my original code works just fine.就 HttpWebRequest 而言,我的原始代码运行良好。

This should work the way you have it written.这应该按照您编写的方式工作。 Can we see the code that actually does the uploading?我们能看到实际上传的代码吗? Are you remembering to close the stream?你记得关闭流吗?

Looking at the example at http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.sendchunked.aspx they still set a content length.查看http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.sendchunked.aspx上的示例,他们仍然设置了内容长度。 Really the bottom line is that if you are sending data you need to tell the receiver how much data you will be sending.真正的底线是,如果您正在发送数据,您需要告诉接收方您将发送多少数据。 Why don't you know how much data you are sending before you send the request?为什么在发送请求之前不知道要发送多少数据?

ContentLength:内容长度:

Property Value Type: System..::.Int64 The number of bytes of data to send to the Internet resource.属性值类型:System..::.Int64 要发送到 Internet 资源的数据字节数。 The default is -1, which indicates the property has not been set and that there is no request data to send.默认值为 -1,表示尚未设置该属性并且没有要发送的请求数据。

Edit for Aaron (I was wrong):为 Aaron 编辑(我错了):

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

From System.Net.HttpWebRequest.SerializeHeaders():来自 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));
}

I prefer to use a generic method to comply this kind of stuff.我更喜欢使用通用方法来遵守这种东西。 Take a look at the XML sender request below.看看下面的 XML 发送方请求。 It will serialize your XML and then send it with the appropriate ContentType :它将序列化您的 XML,然后使用适当的 ContentType 发送它:

public bool SendXMLRequest<T>(T entity, string url, string method)
{
    HttpWebResponse response = null;
    bool received = false;
    try
    {
        var request = (HttpWebRequest)WebRequest.Create(url);
        var credCache = new CredentialCache();
        var netCred = new NetworkCredential(YOUR_LOGIN_HERE, YOUR_PASSWORD_HERE, YOUR_OPTIONAL_DOMAIN_HERE);
        credCache.Add(new Uri(url), "Basic", netCred);
        request.Credentials = credCache;
        request.Method = method;
        request.ContentType = "application/xml";
        request.SendChunked = "GET" != method.ToUpper();

        using (var writer = new StreamWriter(request.GetRequestStream()))
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));

            using (StringWriter textWriter = new Utf8StringWriter())
            {
                serializer.Serialize(textWriter, entity);
                var xml = textWriter.ToString();
                writer.Write(xml);
            }
        }

        response = (HttpWebResponse)request.GetResponse();    
        received = response.StatusCode == HttpStatusCode.OK; //YOu can change the status code to check. May be created, etc...
    }
    catch (Exception ex) { }
    finally
    {
        if(response != null)
            response.Close();
        }

    return received;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM