为什么我用HttpWebReponse得到一个错误的请求(代码400)?

Jul*_*air 5 .net c# wcf json webrequest

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

Json消息:

{"Name":"Julian", "Id":123}
Run Code Online (Sandbox Code Playgroud)

客户端代码:

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();
         }
}
Run Code Online (Sandbox Code Playgroud)

服务器端代码:

 [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
        };
    }
Run Code Online (Sandbox Code Playgroud)

服务器的配置文件

    <?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>
Run Code Online (Sandbox Code Playgroud)

关于代码:

  • (客户端)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=轻松#xx0xx

我尝试过的:

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

电流输出:

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

更新1:

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

  • 创建了Person对象
  • 将Person对象转换为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();
        }

    }  
Run Code Online (Sandbox Code Playgroud)

更新2:

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

System.ArgumentException:Stream无法读取

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

"System.ArgumentException: Stream was not readable."
Run Code Online (Sandbox Code Playgroud)

Jul*_*air 0

我认为问题出在 try 块的第一行。我尝试从请求对象读取响应...呃...虽然我确实尝试从响应对象进一步读取响应,但损坏已经造成。我已将下面的工作代码与导致问题的注释掉的代码一起包含在内。我已经用 **** 标记了有问题的 request.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;
            }
        }
Run Code Online (Sandbox Code Playgroud)