Zeichenfolgen, die über Web-API gesendet werden, werden in Anführungszeichen eingeschlossen

Ich habe ein kleines Problem mit meinen Web-APIs in ASP.NET 4 mit C #. Ich versuche, eine Front-End-GUI zu erstellen, die Daten über mehrere Web-APIs sendet und empfängt. Der Grund für die Verwendung mehrerer APIs hat mit unserem Netzwerk zu tun, das aus mehreren Sicherheitszonen besteht. Die Server befinden sich in unterschiedlichen Zonen, und eine einfache Anforderung muss möglicherweise bis zu 3 verschiedene APIs durchlaufen.

Insbesondere sende ich ein JSON-Objekt von der GUI an die erste API. Das JSON-Objekt soll zur nächsten API und zur nächsten weitergeleitet werden. Von dort aus wird ein neues JSON-Objekt erstellt und im selben Pfad zurückgegeben.

Der Pfad selbst funktioniert gut. Das Problem ist, dass das JSON-Objekt nicht analysiert werden kann, sobald es an die GUI zurückgegeben wird. Ich erhalte eine JSON-Zeichenfolge, die einmal für jede API in Anführungszeichen eingeschlossen wurde.

Die Zeichenfolge kann folgendermaßen beginnen:

Hallo! Ich bin ein String oder ein JSON-Objekt!

Der erste Sprung zwischen den APIs gibt mir folgendes:

“Hey! Ich bin ein String oder eine Art JSON-Objekt!”

Nach dem nächsten Sprung sieht es so aus:

“\”Hallo! Ich bin ein String oder ein JSON-Objekt! \ “”

Und wenn meine GUI es bekommt, haben wir so etwas:

“\” \\ “Hey! Ich bin eine Zeichenfolge oder eine Art JSON-Objekt! \\” \ “”

Hier schlägt das Parsen aus offensichtlichen Gründen fehl. Das JSON-Objekt selbst ist ordnungsgemäß formatiert, aber alle Anführungszeichen verursachen Probleme für den JSON.net-Parser (alle Anführungszeichen innerhalb des Objekts werden auch mehrfach umbrochen).

Was ich bisher ausprobiert habe, ist das Senden der Anfrage als Anwendung / Json-Typ und als Text / Plain-Typ. Beide machten dasselbe. Die APIs geben eine HttpResponseMessage zurück, die mit ReadAsStringAsync () gelesen wird. Ich habe auch versucht, das Lesen der Zeichenfolge zu vermeiden und direkt aus der HttpRequestMessage in eine HttpResponseMessage zu lesen und ReadAsStringAsync () nur in der GUI auszuführen, aber das Problem bleibt bestehen. Die JSON-Zeichenfolge wird mithilfe der JSON.nets Serialize () – Methode erstellt und mithilfe von StringContent () in den HttpContent eingefügt. Dies scheint die Arbeit richtig zu machen. Ich glaube, dass die Anführungszeichen generiert werden, wenn die APIs und die GUI die HttpResponseMessage empfangen.

Gibt es eine Idee, wie ich den JSON-String als unformatierten String senden und empfangen kann, der in keiner Weise behandelt wird?

Ich kann dieses Verhalten umgehen, indem ich das Objekt in jeder API in ein JToken oder ein JObject parse und es erneut serialisiert. Dies ist jedoch keine gute Lösung – ich würde lieber die API einfach so weiterleiten, wie sie es bekommen hat, und nichts damit anfangen. Ich habe mit dem Routing nach Vorwärts gesucht, aber es gibt eine Menge von Berechtigungssachen, die erfordern, dass ich eine API-Aktion und keine Weiterleitungsroute verwende.

Um dies zu klären (TLDR): Die ideale Lösung wäre, wenn die API die Nachricht einfach weitergibt, ohne etwas zu analysieren oder einzulesen. Solange die Quelle der Nachricht autorisiert ist, die Anforderung verschlüsselt ist und die angeforderte URL gültig ist, ist die Nachricht selbst für die einzelnen “Proxy” -APIs nicht von Bedeutung.

Die Anführungszeichen und umgekehrten Schrägstriche werden bei jeder “Proxy” -API hinzugefügt, da der JSON-String für jede Antwort erneut serialisiert wird, nicht wenn die Antwort empfangen wird.

In Ihrer Proxy-API machen Sie vermutlich so etwas (Fehlerbehandlung zur Verkürzung weggelassen):

[HttpGet] public async Task GetWidget(int id) { HttpClient client = new HttpClient(); string url = "http://nextapiserver.example.org/widgets/" + id; string json = await client.GetStringAsync(url); return Request.CreateResponse(HttpStatusCode.OK, json); } 

Das Problem hierbei ist, dass das Web-API standardmäßig davon ausgeht, dass es für die Serialisierung aller von Ihnen gegebenen Informationen verantwortlich ist. Für die meisten Anwendungsfälle ist dies genau das, was Sie möchten. Wenn Ihr Inhalt jedoch bereits in JSON serialisiert ist, kann das Web API dies nicht wissen. Es wird die Zeichenfolge glücklich re-serialisieren und dabei zusätzliche Anführungszeichen und umgekehrte Schrägstriche hinzufügen.

Um eine JSON-Zeichenfolge unberührt zu lassen, müssen Sie das Antwortinhaltsobjekt explizit erstellen (anstatt es der Web-API erstellen zu lassen). Stellen Sie sicher, dass der Medientyp so eingestellt ist, dass nachgeschaltete Clients ihn immer noch als JSON interpretieren (und nicht als Text) ). Hier ist der überarbeitete Code:

 [HttpGet] public async Task GetWidget(int id) { HttpClient client = new HttpClient(); string url = "http://nextapiserver.example.org/widgets/" + id; string json = await client.GetStringAsync(url); HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK); response.Content = new StringContent(json, Encoding.UTF8, "application/json"); return response; } 

Ich bin mir sicher, dass die oben genannten Dosen verbessert wurden, aber das ist das Wesentliche. Probieren Sie es aus und sehen Sie, ob es das Problem für Sie triggers. Beachten Sie, dass Sie diesen Fix auf alle Proxy-APIs anwenden müssen.

Nach vielen Recherchen habe ich es endlich herausgefunden.

Erst einmal; Ich habe die HttpResponseMessage direkt zurückgegeben. Ich habe es nicht absichtlich in jedem Hop entlang des API-Pfads deserialisiert.

Das Problem bestand tatsächlich darin, dass wir eine Mischung der “nativen” MVC-Serialisierungsmethoden und der Methoden von JSON.net verwendeten. Entweder eine für sich ist in Ordnung und bietet ein sauberes Passthrough für alle APIs. Wenn wir jedoch serialisierte Daten aus beiden systemeigenen Methoden und JSON.net-Methoden kombinieren, können die APIs, die sich in der Kette befinden, die Formatierung nicht erkennen und falsch davon ausgehen, dass der Inhalt erneut serialisiert werden sollte (mithilfe systemeigener Methoden).

Die Lösung bestand also einfach darin, alle JSON.net-Methoden aus dem Serialisierungsprozess zu entfernen, und wir hatten die erwarteten Ergebnisse.

Dies ist zwar nicht für jeden etwas, aber ich wollte das Ok () IActionResult von Microsoft.AspNetCore.Mvc verwenden, anstatt die vollständige HttpResponseMessage auszuführen. Dies hatte auch String-Ergebnisse in Anführungszeichen:

 "\"my string result\"" 

Anstatt einen String zurückzugeben, habe ich ein Objekt mit dem Attribut zurückgegeben. Beispiel für die ursprüngliche Ausgabe:

 return Ok(myStringValue); 

Was für mich funktioniert hat:

 return Ok(new { id = myStringValue }); 

Dies hatte den zusätzlichen Vorteil, dass es auf der empfangenden Seite der Anfrage etwas beschreibender war.

Dekorieren Sie die Aktion für ASP.NET Core mit [Produces("text/plain")] .

Z.B.

 [HttpGet("/"), Produces("text/plain")] public IActionResult HelloWorld() => Ok("Hello World"); 

Ich hatte das gleiche Symptom wie im Titel dieses Threads, hatte aber ein anderes Problem, auf das Sie möglicherweise stoßen. Ich habe eine Spalte mit JSON-Daten in SQL Server 2016 (im empfohlenen nvarchar SQL-Datentyp gespeichert). Beim Aufrufen der WEB-API im Browser wurden alle Anführungszeichen in meiner JSON-Spalte mit Escapezeichen versehen (Backslash-Anführungszeichen). In meiner Javascript-GUI führte ich eine JSON.parse für die resultierende JSON durch und konnte die JSON-Daten nicht dereferenzieren. Ich stellte anfangs fest, dass das Problem die Backslashes usw. waren. Es stellte sich jedoch heraus, dass mein Javascript-Code in der Lage war, mit dem Escape-Code gut zu arbeiten. Das eigentliche Problem war, dass ich versucht hatte, die JSON-Daten auf einer untergeordneten Ebene zu demeferenzieren, bevor JSON.parse für die Spaltendaten ausgeführt wurde.

Um genauer zu sein … Stellen Sie sich vor, eine Datenzeile in der database wird als json (“application / json” -Daten an den Browser zurückgegeben) zurückgegeben. Der Aufruf ist myJSONdata. Alle Daten für alle Spalten werden als JSON zurückgegeben, aber eine bestimmte Spalte (nennen Sie sie myJSONcolumn) hat ein JSON-Objekt mit mehreren Ebenen.

Wenn Sie die Unterebene auf diese Weise ableiten, schlägt der Vorgang fehl:

 JSON.parse(myJSONdata["myJSONcolumn"]["sublevel1"]) 

aber das wird funktionieren:

 JSON.parse(myJSONdata["myJSONcolumn"])["sublevel1"] 

Ich habe Microsoft.AspNetCore.Mvc in meinem Web-API-Code verwendet, der mit @ctc identisch ist. Z.B

 var myStringValue = "string value"; return Ok(myStringValue); 

Mein Client-Code hörte auf, die Zeichenfolgen in Anführungszeichen zu setzen, nachdem die Zeile entfernt wurde. DefaultRequestHeaders.Accept auf application/json .

Ursprünglicher Code

 var client = new HttpClient(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var request = new HttpRequestMessage(HttpMethod.Post, "http:///"); request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json"); var httpResponseMessage = client.SendAsync(request).Result; var responseString = httpResponseMessage.Content.ReadAsStringAsync().Result; 

vs modifizierte Version (entfernte die zweite Zeile im obigen Snippet)

 var client = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Post, "http:///"); request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json"); var httpResponseMessage = client.SendAsync(request).Result; var responseString = httpResponseMessage.Content.ReadAsStringAsync().Result; 

Meine Vermutung ist, dass der HttpResponseMessage beim Setzen des Accept- HttpResponseMessage versucht, den Inhalt als Accept- HttpResponseMessage zu HttpResponseMessage , in diesem Fall application/json .

Sie können GetAsync anstelle von GetStringAsync verwenden:

 public async Task Get(int id) { using (HttpClient httpClient = new HttpClient()) { return await httpClient.GetAsync(url); } } 

Behandeln Sie die validations- und Antwortcodes.