it-swarm.com.de

Zeichenfolgen, die über die 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 das Vorhandensein 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 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:

Hey! I am a string, or a JSON object of sorts!

Der erste Sprung zwischen den APIs gibt mir folgendes:

"Hey! I am a string, or a JSON object of sorts!"

Nach dem nächsten Sprung sieht es so aus:

"\"Hey! I am a string, or a JSON object of sorts!\""

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

"\"\\\"Hey! I am a string, or a JSON object of sorts!\\\"\""

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, das Problem bleibt jedoch bestehen. Die JSON-Zeichenfolge wird mithilfe der JSON.nets Serialize () - Methode erstellt und mithilfe von StringContent () in den HttpContent eingefügt. Dies scheint den Job 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 es vorziehen, dass die API die Nachricht genau so weiterleitet, wie sie sie erhalten hat, und nichts damit zu tun hat. Ich habe mit dem Routing nach Vorwärts gesucht, aber es gibt eine Menge von Autorisierungssachen, die erfordern, dass ich eine API-Aktion und keine Weiterleitungsroute verwende.

Um es zu klären (TLDR): Die ideale Lösung wäre, wenn die APIs die Nachricht einfach weiterleiten, 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.

25
kiwhen

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 aus den "nativen" MVC-Serialisierungsmethoden und den 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 von beiden systemeigenen Methoden und JSON.net-Methoden kombinieren würden, könnten die APIs, die sich in der Kette befinden, die Formatierung nicht erkennen und falsch davon ausgehen, dass der Inhalt (mit systemeigenen Methoden) erneut serialisiert werden sollte.

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

8
kiwhen

Die Anführungszeichen und umgekehrten Schrägstriche werden an jeder "Proxy" -API hinzugefügt, da die JSON-Zeichenfolge für jede Antwort neu serialisiert wird, nicht wenn die Antwort empfangen wird.

In Ihrer Proxy-API machen Sie vermutlich so etwas (Fehlerbehandlung aus Gründen der Kürze):

[HttpGet]
public async Task<HttpResponseMessage> 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 vergebenen Informationen verantwortlich ist. Für die meisten Anwendungsfälle ist dies genau das, was Sie möchten. Wenn Ihr Inhalt bereits zu 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 (und nicht als Text) interpretieren ). Hier ist der überarbeitete Code:

[HttpGet]
public async Task<HttpResponseMessage> 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 Dinge verbessert werden können, aber das ist der Kernpunkt davon. Probieren Sie es aus und sehen Sie, ob es das Problem für Sie löst. Beachten Sie, dass Sie diesen Fix auf all die Proxy-APIs anwenden müssen.

40
Brian Rogers

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

Z.B.

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

Dies ist möglicherweise 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 der ursprünglichen 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.

1
ctc

Ich hatte das gleiche Problem mit System.Web.Http.ApiController, da ich von Hand zu JSON serialisiert wurde, bevor ich das Ergebnis zurückgegeben habe (JsonHelperis ist eine Hilfsklasse von uns, die Newtonsoft.Json.JsonConvert umgibt):

var jason = JsonHelper.SerializeToJson(result);
return Ok(jason);

Dies führte zu demselben "\"{ ... }\""-Effekt. Die Vorserialisierung war notwendig, da wir einige spezifische Regeln für den Serialisierungsprozess haben.

Glücklicherweise gibt es einen System.Web.Http.Results.JsonResult<T>, der dasselbe tun kann:

return new JsonResult<MyDataType>(result, JsonHelper.Settings, Encoding.UTF8, this);
0
Dee J. Doena

Ich hatte dieses Problem und habe Newtonsoft.Json Über Nuget Packages Manager installiert. So deserialisieren Sie Ihre JSON-Zeichenfolge:

string deserializedString = JsonConvert.DeserializeObject<string>(yourJsonString);

Vergessen Sie nicht, den Namespace zu importieren:

using Newtonsoft.Json;

0
Santiago Trejo

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 DefaultRequestHeaders.Accept zu application/json entfernt wurde.

Ursprünglicher Code

var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var request = new HttpRequestMessage(HttpMethod.Post, "http://<Host>/<Path>");
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://<Host>/<Path>");
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 durch das Setzen des Accept-Headers die HttpResponseMessage versucht, den Inhalt als Accept-Headereinstellung zu speichern, in diesem Fall application/json.

0
Shinbo

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 zuerst 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 versuchte, die JSON-Daten auf einer untergeordneten Ebene vor - mit JSON.parse auf die Spaltendaten zu dereferenzieren.

Um genauer zu sein ... Stellen Sie sich vor, eine Datenzeile in der Datenbank 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) verfügt über ein JSON-Objekt, das mehrere Ebenen umfasst. 

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"]
0
sarora