2016-04-02 100 views
5

Sto inviando un semplice messaggio JSON a un'applicazione server WCF. messaggioPerché ottengo una richiesta errata (codice 400) con HttpWebReponse?

JSON:

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

client codice lato:

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

codice lato server:

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

file server di configurazione

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

Informazioni sul codice:

  • (lato client) L'ingresso al metodo makeRequest è solo i dati JSON sopra riportati.
  • (lato client) L'URI che viene postata è solo "localhost: 8732/service1/postdata" (sì incluso http: // non è possibile includerlo qui poiché conta come un link e posso avere solo due apparentemente)
  • (lato server) Il codice del server è un'implementazione di questa soluzione che ho trovato al codice Progetto:

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

Quello che ho provato:

  • Ho usato Postman per inviare un messaggio JSON a uri sopra e ho ricevuto una risposta (per ora restituisce solo un pacchetto con gli stessi dati) quindi ho difficoltà a trovare problemi nell'URI.
  • Ho convalidato il pacchetto json con JSONLint.
  • Ho aggiunto vari blocchi try/catch per ottenere più informazioni di errore ma ammontano tutti a errore di protocollo/errore errato codice di richiesta 400.
  • Ho anche distrutto le cose nella mia mente (è più economico e meno allarmante per il mio coinquilino)

corrente di uscita:

ottengo una risposta cattiva richiesta dal server senza dati.

Update 1:

Devo essere stato sempre l'ordine di conversione di dati errati.Prima che:

  • oggetto Person creato
  • oggetto Person convertito json
  • JSON passato al metodo makeRequest
  • (in makeRequest) creato WebRequest json conversione in matrice di byte

La prima if-statement del metodo MakeRequest() (lato client) è stato aggiornato con un segmento di codice che effettua la richiesta con il json come è. Io ora ottenere un errore di violazione del protocollo quando write.Flush() esegue: errore di

La violazione del protocollo da:

Aggiornato il codice lato client (metodo 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(); 
     } 

    } 

Update 2 la chiamata streamWriter.Flush() era perché non avevo impostato la request.ContentLenth. Ora ho impostato il Content.Length per json.Length ed io ora ottenere questo errore:

System.ArgumentException: Stream was not readable

L'immagine è un po 'piccola, ma il messaggio di errore si legge:

"System.ArgumentException: Stream was not readable." 

risposta

0

Penso il problema era nelle prime righe del blocco try. Provo a leggere la risposta dall'oggetto di richiesta ... ehem ... Sebbene abbia provato a leggere la risposta dall'oggetto risposta , il danno era già stato eseguito. Ho incluso il codice di lavoro di seguito insieme al codice commentato che stava causando il problema. Ho contrassegnato la richiesta incriminata. GetResponse() con **** e la risposta corretta. GetResponseStream() che sarai felice di sentire, è ora libera di fare il suo lavoro.

Spero che questo risparmi un sacco di tempo!

Tutte le parti pertinenti del metodo 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; 
      } 
     } 
0

Quando si leggono un flusso fino alla fine, devi ricominciare dall'inizio.

Si può provare questo:

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

non ha riparato il problema - ha ottenuto un qualcosa di un'eccezione su operazioni di ricerca non essere supportato dal torrente? Ora ho una soluzione! –