2016-07-27 2 views
22

Vor einiger Zeit habe ich Code implementiert, um eine REST Api mit der Klasse HttpClient zu konsumieren.HttpRequestException - Ist das ein Client- oder Serverproblem?

using (var client = new HttpClient() { BaseAddress = new Uri(@"https://thirdparty.com") }) 
{ 
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(...); 

    var uri = new Uri(@"rest/api/foo", UriKind.Relative); 
    var content = new StringContent(json.ToString()); 

    using (var response = await client.PostAsync(uri, content)) 
    { 
     // etc ... 
    } 
} 

Dieser Code schien völlig in Ordnung, sowohl gegen die Test- und Produktionsumgebungen (von denen jeder eine Test/Produktion uri Zugriff) zu arbeiten. Vor kurzem haben wir begonnen, nur eine HttpRequestException in der Produktionsumgebung zu erhalten: System.Net.Http.HttpRequestException: Error while copying content to a stream.

Das ist ein bisschen seltsam schien, so habe ich Postman die gleiche Botschaft senden und es funktionierte gut. Ich war mir nicht sicher, warum unser Code versagte und Postman arbeitete. Ich habe einen Parameter in den JSON-Daten (der Status von "NY" zu "NV") geändert und unser .NET-Code hat gut funktioniert - natürlich können wir nicht einfach die falschen JSON-Daten senden, also ist dies keine Lösung; Dies war eher eine Beobachtung, dass der exakt gleiche Code mit unterschiedlichen Inhalten funktionierte.


Interessant ist, dass wir zwei Codeänderungen vornehmen können, die das beheben werden. Erstens kann Postman mit dem RestSharp Paket einen funktionierenden C# -Code generieren. Alternativ fand ich eine answer von einer anderen Frage zeigt auf mit HttpVersion 1,0:

using (var request = new HttpRequestMessage(HttpMethod.Post, uri)) 
{ 
    request.Version = HttpVersion.Version10; 
    request.Content = new StringContent(json.ToString()); 

    using (var response = await client.SendAsync(request)) 
    { 
     // etc ... 
    } 
} 

Das verwirrende Teil ist, dass Postman die HTTP/1.1-Version verwendet. Also, in Zusammenfassung:

  • Wenn wir die JSON-Daten ändern (US-Bundesstaat von "NY" zu "NV"), funktioniert der Code.
  • Derselbe exakte JSON und Code funktioniert gegen die Test-URI.
  • Das Ändern des Codes für die Verwendung des RestSharp-Pakets funktioniert.
  • Das Ändern des Codes für die Verwendung von HTTP/1.0 anstelle von HTTP/1.1 funktioniert.
  • Warum in aller Welt ist Postman in der Lage, mit HTTP/1.1 zu arbeiten, aber HttpClient schlägt fehl? Ist das ein Problem mit unserem Kunden (der Code funktioniert für andere US-Staaten)? Ist das ein Fehler in .NET Framework? Ist etwas falsch mit der Implementierung/Hosting der REST Api von der dritten Partei?


    Postman Header:

    POST rest/api/foo HTTP/1.1 
    Host: thirdparty.com 
    Content-Type: application/json 
    Authorization: Basic SOME_ENCRYPTED_USER_PASS 
    Cache-Control: no-cache 
    Postman-Token: 2fa5b5a0-b5d3-bd4c-40f0-d2b55b60316b 
    

    Probe Json:

    { 
        "stateCode": "NY", 
        "packageID": "58330", 
        "name": "58330-PRI-1", 
        "documents": [ 
         { 
          "type": "SPECIAL", 
          "name": "Sample Document", 
          "documentID": "3569976" 
         } 
        ], 
        "descriptions": [ 
         { 
          "city": "New York", 
          "state": "NY" 
         } 
        ] 
    } 
    

    Stacktrace:

    AggregateException: One or more errors occured. 
    HttpRequestException: Error while copying content to a stream. 
    IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. 
    SocketException: An existing connection was forcibly closed by the remote host. 
    
    +0

    Ist der Text des Postboten genau so wie der mit client.PostAsync() gesendete Text? Ich glaube, der Unterschied zwischen den Versionen ist der Keep-Alive-Header, so dass es möglich sein könnte, dass Postman Timeouts anders behandelt als .NET. –

    +0

    @NickSpicer: Richtig, der Körper ist die gleichen JSON-Daten. Und ich glaube, es ist die Tatsache, dass es HTTP/1.1 vs HTTP/1.0 ist, die die Verbindung keep-alive vs close bestimmt. Ich habe meine Antwort aktualisiert, um die Briefkopfdaten hinzuzufügen. –

    +0

    Haben Sie die Details der HttpRequestException verfolgt? –

    Antwort

    1

    Aufgrund der Tatsache, dass Sie die Daten leicht und es ändern können haben gelingen, ich würde sagen, Ihre Probleme haben nichts mit deinem Code zu tun haben. Was passiert, wenn der Server einen ungültigen Wert zwischengespeichert hat und Ihnen weiterhin diesen Wert sendet, bis der Cache gelöscht ist?

    Versuchen Sie sagen implizit den Server nicht im Cache gespeichert Werte zu verwenden ...

    using (var client = new HttpClient() { BaseAddress = new Uri(@"https://thirdparty.com") }) 
    { 
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(...); 
    
        var uri = new Uri(@"rest/api/foo", UriKind.Relative); 
        var content = new StringContent(json.ToString()); 
    
        client.DefaultRequestHeaders.CacheControl = CacheControlHeaderValue.Parse("no-cache"); 
    
        using (var response = await client.PostAsync(uri, content)) 
        { 
         // etc ... 
        } 
    } 
    

    und sehen, ob Sie eine gültige Antwortstream erhalten.

    +0

    Leider bekomme ich die selbe Ausnahme.Die Option "no-cache" hat nichts geändert. –

    +0

    verwenden Sie response.Content.ReadAsStringAsync() oder ReadAsStreamAsync/ReadAsByteArrayAsync? – TwistedStem

    +0

    Ich bin mir nicht sicher, wie das von Bedeutung ist, da die Ausnahme in der Zeile "client.PostAsync (uri, content)" ausgeführt wird? Alles danach ist egal. –

    0

    Haben Sie Antivirus/Firewall auf dem Rechner, auf dem der HttpClient läuft? In der Vergangenheit hatte ich Probleme mit AVG, McAfee, Norton und anderen, die im Stillen Anfragen blockierten. Es ist ziemlich schwierig, genau herauszufinden, wo, aber es gibt möglicherweise eine Registerkarte, auf der die Ports überwacht werden. Das Deaktivieren/Deaktivieren kann helfen, das Problem zu identifizieren. Wenn dies der Fall ist, ist die richtige Lösung, Ihre "thirdparty.com" auf einer weißen Liste der entsprechenden Anbieter zu bekommen.

    Es lohnt sich vielleicht auch, Ihre Antwortheader von Ihrem Server aus zu betrachten? Können Sie sie zu Ihrer Frage hinzufügen? Nur weil ich in der Vergangenheit Content-Security-Policy-Header gefunden habe, die verhindern, dass einige meiner Anfragen abgeschlossen werden?

    Verwandte Themen