为什么我使用HttpWebReponse收到错误的请求(代码400)?

时间:2016-04-02 17:29:34

标签: c# .net json wcf webrequest

我正在向WCF服务器应用程序发送一条简单的json消息。

Json消息:

{"Name":"Julian", "Id":123}

客户端代码:

public string MakeRequest(string parameters)
{
        Console.WriteLine("parameters:" + parameters);

        var request = (HttpWebRequest)WebRequest.Create(EndPoint);
        request.Method = Method.ToString();
        request.ContentLength = 0;
        request.ContentType = ContentType;

        Console.WriteLine("request: " + request.Headers.ToString());

        if (PostData != null && Method == HttpVerb.POST)
        {
            var encoding = new UTF8Encoding();
            var bytes = ObjectToByteArray(PostData);
            request.ContentLength = bytes.Length;
            Console.WriteLine("Content length: " + request.ContentLength); 

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

        try
        {
            using (var response = (HttpWebResponse)request.GetResponse())
            {
                var responseValue = string.Empty;

                if (response.StatusCode != HttpStatusCode.OK)
                {
                    var message = String.Format("Request failed. Received HTTP {0}", response.StatusCode);
                    throw new ApplicationException(message);
                }

                // grab the response
                using (var responseStream = response.GetResponseStream())
                {
                    if (responseStream != null)
                        using (var reader = new StreamReader(responseStream))
                        {
                            responseValue = reader.ReadToEnd();
                        }
                }

                return responseValue;
            }
        }
        catch (WebException exception)
        {
            string responseText;

            using (var reader = new StreamReader(exception.Response.GetResponseStream()))
            {
                responseText = reader.ReadToEnd();
                return responseText;
            }
        }

private byte[] ObjectToByteArray(object obj)
{
        if (obj == null)
            return null;
        BinaryFormatter bf = new BinaryFormatter();
        using (MemoryStream ms = new MemoryStream())
        {
            bf.Serialize(ms, obj);
            return ms.ToArray();
         }
}

服务器端代码:

 [WebInvoke(Method = "POST",
                ResponseFormat = WebMessageFormat.Json,
                RequestFormat =WebMessageFormat.Json,
                UriTemplate = "/postdata")]
    public Person PostData(Person data)
    {
        //Return new person with data inputted from json message
        return new Person()
        {
            Id = data.Id,
            Name = data.Name
        };
    }

服务器的配置文件

    <?xml version="1.0"?>
<configuration>
  <system.serviceModel>

  <services>
      <service name="WcfJsonRestService.Service1" behaviorConfiguration="Metadata">
      <host>
        <baseAddresses>
          <add baseAddress="http://localhost:8732/service1"/>
        </baseAddresses>
      </host>
          <endpoint address="http://localhost:8732/service1" 
                  binding="webHttpBinding" 
                  contract="WcfJsonRestService.IService1"/>
      </service>
    </services>

    <behaviors>
    <serviceBehaviors>
      <behavior name="Metadata">
        <serviceMetadata httpGetEnabled="true" policyVersion="Policy15"/>
        <serviceDebug includeExceptionDetailInFaults="true"/>
      </behavior>
    </serviceBehaviors>

    <endpointBehaviors>
          <behavior>
            <webHttp />
          </behavior>
      </endpointBehaviors>
    </behaviors>

  </system.serviceModel>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>

关于代码:

  • (客户端)MakeRequest方法的输入只是上面显示的json数据。
  • (客户端)被发布的Uri只是“localhost:8732 / service1 / postdata”(是的,包括http://只是不能在这里包含它,因为它算作一个链接,我只能有两个显然)
  • (服务器端)服务器代码是我在Code Project中找到的此解决方案的实现:

http://www.codeproject.com/Articles/167159/How-to-create-a-JSON-WCF-RESTful-Service-in-sec?fid=1614381&fr=1&df=90&mpp=25&prof=False&sort=Position&view=Normal&spc=Relaxed#xx0xx

我尝试了什么:

  • 我使用Postman将json消息发送到上面的uri并收到了响应(现在它只返回一个包含相同数据的包)所以我很难在uri中找到任何问题。
  • 我已经使用JSONLint验证了json包。
  • 我添加了各种try / catch块以获取更多错误信息,但它们都等于协议错误/错误请求错误代码400.
  • 我也在脑子里砸了一些东西(这对我的室友来说更便宜,也不那么惊人)

当前输出:

我从没有数据的服务器收到错误的请求响应。

更新1:

我一定是弄错了数据转换顺序。在我之前:

  • 创建了人物对象
  • 将人物对象转换为json
  • 将json传递给MakeRequest方法
  • (在MakeRequest中)创建了将json转换为字节数组的WebRequest

MakeRequest()方法(客户端)的第一个if语句已使用代码段进行更新,该代码段使用json 生成请求。我现在在write.Flush()执行时遇到协议违规错误:

更新了客户端代码(MakeRequest方法)

if (PostData != null && Method == HttpVerb.POST)
    {
        //var encoding = new UTF8Encoding();
        //var bytes = ObjectToByteArray(PostData);
        //request.ContentLength = bytes.Length;
        //Console.WriteLine("Content length: " + request.ContentLength); 

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


        using (var streamWriter = new StreamWriter(request.GetRequestStream()))
        {
            streamWriter.Write(json);
            streamWriter.Flush();
            streamWriter.Close();
        }

        var httpResponse = (HttpWebResponse)request.GetResponse();
        using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
        {
            var result = streamReader.ReadToEnd();
        }

    }  

更新2:

来自streamWriter.Flush()调用的协议违规错误是因为我没有设置request.ContentLenth。我现在已将Content.Length设置为json.Length,现在我收到此错误:

System.ArgumentException: Stream was not readable

图像有点小但错误信息显示为:

"System.ArgumentException: Stream was not readable."

2 个答案:

答案 0 :(得分:0)

当您将流读到最后时,您必须将其追回到开头。

你可以试试这个:

StreamReader sr = new StreamReader(stream);
sr.ReadToEnd();
stream.Seek(0, SeekOrigin.Begin); 
sr.ReadToEnd(); // This should work now

答案 1 :(得分:0)

我认为问题出现在try块的第一行。我尝试从请求对象中读取响应...嗯......虽然我确实尝试从响应对象读取响应,但是已经完成了损坏。我已将下面的工作代码与导致该问题的注释掉的代码一起包括在内。我已经用****标记了违规请求.GetResponse()以及你很乐意听到的正确的response.GetResponseStream(),现在可以自由地完成它的工作了。

希望这可以节省很多时间!

MakeRequest方法的所有相关部分:

var request = (HttpWebRequest)WebRequest.Create(EndPoint);
        request.Method = Method.ToString();
        request.ContentLength = 0;
        request.ContentType = ContentType;


        Console.WriteLine("request: " + request.Headers.ToString());

        if (PostData != null && Method == HttpVerb.POST)
        {
            Console.WriteLine("json length: " + json.Length);
            Console.WriteLine(json);
            request.ContentLength = json.Length;
            var encoding = new UTF8Encoding();             

            using (var streamWriter = new StreamWriter(request.GetRequestStream()))
            {
                streamWriter.Write(json);
                streamWriter.Flush();
                streamWriter.Close();
            }
        }

        try
        {
            // ****    FIRST READ USING request.GetResponse()    ****
            //var httpResponse = (HttpWebResponse)request.GetResponse();
            //using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
            //{
            //    streamReader.ReadToEnd();
            //}

            using (var response = (HttpWebResponse)request.GetResponse())
            {
                var responseValue = string.Empty;

                if (response.StatusCode != HttpStatusCode.OK)
                {
                    var message = String.Format("Request failed. Received HTTP {0}", response.StatusCode);
                    throw new ApplicationException(message);
                }

                // grabs the response
                using (var responseStream = response.GetResponseStream())
                {
                    if (responseStream != null)
                        using (var reader = new StreamReader(responseStream))
                        {
                            //  ****    SECOND READ USING response.GetResponseStream()    ****
                            responseValue = reader.ReadToEnd();
                        }
                }
                return responseValue;
            }
        }