2017-01-27 2 views
14

Ich habe gerade meinen mvc-Dienst aktualisiert, um größere Fehler und Protokollierung hinzuzufügen. Ich habe jetzt genau diesen Fehler mehrmals. Aber kann nicht replizieren.Warum wird meine Ajax Post abgeschnitten?

Unterminated string. Expected delimiter: ". Path 'Breadcrumbs[18].Params', line 1, position 59740. at Newtonsoft.Json.JsonTextReader.ReadStringIntoBuffer(Char quote) at 

Der Weg ist jedes Mal anders, je nachdem, was der Benutzer an den Server sendet.

Meine AJAX-Anfragen sehen in der Regel wie folgt aus:

$.ajax(myURL("SendBreadcrumbs"), { 
      type: "POST", 
      cache: false, 
      data: { telemetry: telemetry.JSONify(), userID: currentUser, isMyVI: isMyVI } 
     }) 

In diesen Fällen userID und isMyVI (boolean) didnt existieren und die Telemetrie Zeichenfolge abgeschnitten.

JSONify Methode ist wie folgt:

self.JSONify = function() { 
    var data = ko.mapping.toJSON(self, TelemetryMapping); 
    return data; 
} 

Diese knockoutJSs Serialisierer ist.

Server Side:

public void SendBreadcrumbs(string telemetry, string userID = null, bool isMyVI = true) 
{ 
    MyServiceAudit audit; 
    Guid UserID; 
    if (Guid.TryParse(userID, out UserID)) 
     audit = InsertAudit(UserID); 
    else 
     audit = InsertAudit(null); 
    try 
    { 
     Models.Telemetry data = JsonConvert.DeserializeObject<Models.Telemetry>(telemetry); 
     Controllers.Telemetry.UpdateTelemetry(data, isMyVI); 
    } 
    catch (Exception ex) 
    { 
     MyServiceAuditDB.FailAudit(audit.ID, ex.Message + " " + ex.StackTrace); 
    } 
} 

ich völlig ratlos bin, ich habe versucht, auf dem Server die web.config Aktualisierung mit größeren MAXWERTE etc, seine auf der Seite abgeschnitten zu sehen.

Der einzige andere Unterschied, den ich in meinem Ajax habe, ist ein globales Timeout von 3 Minuten.

Ist dies so einfach wie Sonderzeichen nicht auf Client-Seite oder Server-Seite Einschränkungen behandelt, oder ist die Daten so groß es wird Chunked und Server-Seite weiß nicht auf den nächsten Chunk warten?

+0

Wie groß ** ist ** die Daten? – stuartd

+0

Es ist so lang wie ein Stück Schnur tbh. Ich notiere die HTTP-Parameter vor der Deserialisierung usw. (HttpContext.Request.Params.ToString()). Also eine der fehlgeschlagenen Anfragen das ist 117.454 Zeichen lang? –

+0

Auch nur überprüft habe ich Params dieser Größe 3.119.214. Was ist nicht gescheitert? Kann ich die Kürzung aufgrund der Größe ausschließen? –

Antwort

0

Mit Hilfe von ein paar Kommentaren, Antworten und schließlich Live-Daten gescheitert, konnte ich das beheben.

Es stellte sich heraus, dass der Benutzer nicht nur Sonderzeichen verwendet, sondern auch einige der gesendeten statischen Daten enthalten diese (GIGO - konnte nicht den Zustand einiger unserer Daten glauben).

Client Side Lösung:

Die encodeURIComponent() Funktion eine Komponente URI codiert. Diese Funktion codiert Sonderzeichen. Darüber hinaus codiert es die folgenden Zeichen:, /? : @ & = + $ #

$.ajax(myURL("SendBreadcrumbs"), { 
     type: "POST", 
     cache: false, 
     data: { telemetry: encodeURIComponent(telemetry.JSONify()), userID: currentUser, isMyVI: isMyVI } 
    }) 

Server Side Lösung:

Wandelt einen String in seine unescaped Darstellung. Uri.UnescapeDataString()

public void SendBreadcrumbs(string telemetry, string userID = null, bool isMyVI = true) 
{ 
    MyServiceAudit audit; 
    Guid UserID; 
    if (Guid.TryParse(userID, out UserID)) 
     audit = InsertAudit(UserID); 
    else 
     audit = InsertAudit(null); 
    try 
    { 
     Models.Telemetry data = JsonConvert.DeserializeObject<Models.Telemetry>(Uri.UnescapeDataString(telemetry)); 
     Controllers.Telemetry.UpdateTelemetry(data, isMyVI); 
    } 
    catch (Exception ex) 
    { 
     MyServiceAuditDB.FailAudit(audit.ID, ex.Message + " " + ex.StackTrace); 
    } 
} 

Web Application Konfiguration:

hatte ich einen Benutzer bekommt einen 500-Fehler, aufgrund versuchen, 20 E-Mails zu senden. Ich habe die Konfiguration aktualisiert, um die maximale Anforderungslänge (in Kilobyte, Beispiel ist 1 GB) und maximale Inhaltslänge (in Bytes, Beispiel ist 1 GB) aufzunehmen. E-Mails kamen durch kein Problem. Ich konnte es nicht glauben!

<appSettings> 
    <add key="aspnet:MaxJsonDeserializerMembers" value="150000" /> 
</appSettings> 
<system.web> 
    <httpRuntime targetFramework="4.5" maxQueryStringLength="32768" maxUrlLength="65536" maxRequestLength="1048576" /> 
</system.web> 
<system.webServer> 
    <security> 
     <requestFiltering> 
      <requestLimits maxQueryString="32768" maxAllowedContentLength="1073741824" /> 
     </requestFiltering> 
    </security> 
</system.webServer> 
<system.web.extensions> 
    <scripting> 
     <webServices> 
      <jsonSerialization maxJsonLength="2147483647" /> 
     </webServices> 
    </scripting> 
</system.web.extensions> 
0

Sie geben nicht an, welche Version von jQuery Sie verwenden, aber wenn wir von einer stabilen Version ausgehen, können wir sicher sein, dass die erforderliche Kodierung und das Escapen in der Downline von $.ajax() fehlerfrei ist.

Wenn die Länge der Anfrage die Ursache war, würden wir einen HTTP-Fehler auf der Clientseite und keinen Aufruf der serverseitigen Funktion sehen ("max request length exceeded"). Dies wird durch Ihre Beobachtung unterstützt, dass Anfragen mit längeren Strings erfolgreich sein können, während kürzere Strings fehlschlagen können.

würde ich zwei Aktionen vorschlagen:

1) eine Fragmentierung zu reduzieren, Schichtung und mögliche irreführende Diagnosen, nicht JSONify nur die Telemetrie. Construct das Objekt aus Telemetrie, userID und isMyVi, dann JSONify dass als Ganzes (das bedeutet, umfassen die Metadaten in der TelemetryMapping Beschreibung, wenn möglich)

2) Überprüfen Sie den Wert von telemetry.JSONify() zur Laufzeit clientseitige . Wenn Sie feststellen, dass die Kürzung dadurch verursacht wird, konzentrieren Sie sich auf die Version und Integrität von knockoutJS oder ersetzen Sie sie. Wie @Destrif in ihrem Kommentar weist darauf hin, schlägt https://stackoverflow.com/a/21565447/1132334, dass es nicht Teil der knockoutJS Aufgaben sein kann doppelte Anführungszeichen, Schrägstriche zu entkommen und schlitzt -

die so einfach sein kann, in einer anderen escape() den Anruf als Verpackung:

self.JSONify = function() { 
    var data = escape(ko.mapping.toJSON(self, TelemetryMapping)); 
    return data; 
} 
+0

Die Escape() - Funktion wurde in der JavaScript-Version 1.5 nicht mehr unterstützt. Verwenden Sie stattdessen encodeURI() oder encodeURIComponent(). –

1

Ich schlage vor, Sie verwenden den Fiddler für die grobe Vorstellung, welche Daten tatsächlich gesendet werden. Es ist sicherlich das Problem der Deserialisierung und Ihr Code sieht absolut gut aus. Die Größe der Daten sollte hier kein Problem sein, man sollte etwas Rohdaten sehen und es sollte in Ordnung sein.

Auch sehen, wenn die JSonify() die Daten korrekt formatiert, ohne die Zeichenfolge zu entkommen.

1

Verwenden Sie encodeURIComponent für den vom Benutzer eingegebenen Inhalt.