发送POST请求时发生ProtocolViolationException

时间:2014-06-25 19:23:26

标签: c# rest http-post

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

当我在下面发送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();
    }

1 个答案:

答案 0 :(得分:3)

一些事情:

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

此外,您需要在调用Close()

之前在流上调用GetResponse()
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方法时,您必须获取请求流,写入要发布的数据,然后关闭流。此方法阻止等待内容发布;如果没有超时设置并且您不提供内容,则调用线程将无限期地阻塞。