Why am I getting a bad request (code 400) with HttpWebReponse?

I am sending a simple json message to a WCF server application.

Json post:

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

Client Code:

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

Server Side Code:

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

Server configuration file

  <?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> 

About the code:

  • (client side) Entering the MakeRequest method is just the json data shown above.
  • (Client side). The uri that goes to the site is "localhost: 8732 / service1 / postdata" (yes, including http: // just can't include it here since it is considered a link, and I can only have two)
  • (server side) Server code is the implementation of this solution that I found in the 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

What I tried:

  • I used Postman to send a json message to the aforementioned uri and got a response (at the moment it just returns a packet with the same data), so it is difficult for me to find any problems in the uri.
  • I checked json package with JSONLint.
  • I have added various try / catch blocks to get additional error information, but they all represent error code 400 / request error 400.
  • I also broke things in my mind (it's cheaper and less disturbing for my flatmate).

Current output:

I get a bad request from a server without data.

Update 1:

I must have misconfigured the data conversion order. Before I:

  • created Person object
  • converted Person object to json
  • json to MakeRequest method passed
  • (in MakeRequest) a WebRequest was created that converts json to a byte array

The first if-statement of the MakeRequest () method (client side) has been updated with a code segment that makes a request using json as is. Now I get a protocol violation error when write.Flush () does:

Updated client-side code (MakeRequest method)

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

Update 2:

The protocol violation error from calling streamWriter.Flush () was that I did not set request.ContentLenth. I set Content.Length to json.Length and now I get this error:

System.ArgumentException: stream cannot be read

The image is a bit small, but the error message reads:

 "System.ArgumentException: Stream was not readable." 
+5
source share
2 answers

I think the problem was in the first lines of the try block. I am trying to read the response from the request object ... ehem ... Although I tried to read the response from the response object further, damage has already been done. I included the working code below along with the commented code that caused the problem. I noted the offensive .GetResponse () request with ****, as well as the correct answer. GetResponseStream (), which you will love to hear, is now free to do its job.

Hope this saves you a lot of time!

All relevant parts of the MakeRequest method:

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

When you read a stream to the end, you should look for it at the beginning.

You can try the following:

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

Source: https://habr.com/ru/post/1246310/


All Articles