【问题标题】:ProtocolViolationException while sending POST request发送 POST 请求时发生 ProtocolViolationException
【发布时间】:2014-06-25 19:23:25
【问题描述】:

我已经阅读了其他类似的问题并尝试了这些问题的解决方案,但由于这不起作用,因此我将其发布在这里。

当我在下面发送 POST 请求时,它失败并显示以下错误消息:

System.Net.ProtocolViolationException: You must write ContentLength bytes to the request stream before calling [Begin]GetResponse.
   at System.Net.HttpWebRequest.GetResponse()
   ....
   ....

我对其他 URL 端点的 GET 请求工作正常,我只是在发出 POST 请求时遇到这个问题。另外,我已经在代码中适当地设置了 ContentLength。我仍然无法发送 POST 请求。想法?

public void TestSubmitJobWithParams1()
    {
        const string RestActionPath = "URL_GOES_HERE";

        // if you have multipe parameters seperate them with teh '&' delimeter.
        var postData = HttpUtility.UrlEncode("MaxNumberOfRowsPerSFSTask") + "=" + HttpUtility.UrlEncode("3000");

        var request = (HttpWebRequest)WebRequest.Create(RestActionPath);
        request.Method = "POST";
        request.Credentials = CredentialCache.DefaultCredentials;
        request.PreAuthenticate = true;
        request.ContentLength = 0;
        request.Timeout = 150000;
        request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
        request.ContentType = "application/x-www-form-urlencoded";

        byte[] bytes = Encoding.ASCII.GetBytes(postData);

        request.ContentLength = bytes.Length;

        Stream newStream = request.GetRequestStream();

        newStream.Write(bytes, 0, bytes.Length);


        string output = string.Empty;
        try
        {
            using (var response = request.GetResponse())
            {
                using (var stream = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(1252)))
                {
                    output = stream.ReadToEnd();
                }
            }
        }
        catch (WebException ex)
        {
            if (ex.Status == WebExceptionStatus.ProtocolError)
            {
                using (var stream = new StreamReader(ex.Response.GetResponseStream()))
                {
                    output = stream.ReadToEnd();
                }
            }
            else if (ex.Status == WebExceptionStatus.Timeout)
            {
                output = "Request timeout is expired.";
            }
        }
        catch (ProtocolViolationException e)
        {
            Console.WriteLine(e);
        }

        Console.WriteLine(output);
        Console.ReadLine();
    }

【问题讨论】:

  • 您确定要使用 ASCII 编码吗?这会将任何代码高于 127 的字符变成问号。这将导致您的程序在美国英语以外的几乎所有语言环境中都失败,而且很可能会失败。

标签: c# rest http-post


【解决方案1】:

一些事情:

首先,您不需要直接设置ContentLength - 只需将其保留(默认为-1)。你实际上调用了它两次,所以删除这两个调用。

另外,在调用GetResponse()之前,您需要在流上调用Close()

Stream newStream = request.GetRequestStream();

newStream.Write(bytes, 0, bytes.Length);
newStream.Close();

或者,您可以在 using 语句中使用它,该语句为您处理关闭和处置):

using (var newStream = request.GetRequestStream())
{
    newStream.Write(bytes, 0, bytes.Length);
}

从技术上讲,您也不需要将 HttpUtility.UrlEncode() 用于 postData,因为您的字符串中没有任何内容会违反 Url 的完整性。做吧:

string postData = "MaxNumberOfRowsPerSFSTask=3000");

让我知道这是否可以解决您的问题。

如需更详尽的概述,请查看:http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.getresponse.aspx

具体来说,关于ProtocolViolationException 的部分以及它所说的位置:

使用POST方式时,必须获取请求流,写入要发布的数据,关闭流。此方法阻止等待内容发布;如果没有设置超时并且您不提供内容,则调用线程将无限期阻塞。

【讨论】:

    猜你喜欢
    • 2016-06-02
    • 2022-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-25
    • 2017-07-13
    • 2010-10-12
    • 2016-03-24
    相关资源
    最近更新 更多