2017-01-27 9 views
14

私は大きなエラーとロギングを含むように自分のmvcサービスを更新しました。私は今この正確なエラーを何度も持っています。しかし、複製することはできません。なぜ私のajax投稿が切り捨てられていますか?

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

パスは、ユーザーがサーバーに送信する内容によって異なります。

私のAJAXリクエストは、一般的に次のようになります。これらのケースでは

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

、ユーザーIDとisMyVI(ブール値)が存在していませんでし及びテレメトリ文字列は切り捨てられます。次のように

JSONify方法がある:

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

これはknockoutJSsシリアライザあります。

サーバーサイド:

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

私は完全に困惑しています、私は、その、その側に切り捨て見るために、より大きなmaxvaluesなどでサーバー上のweb.configファイルを更新しようとしています。

私のajaxで唯一の違いは、3分のグローバルタイムアウトです。

これは、クライアント側やサーバー側の制限で処理されない特殊文字、またはそれほど大きくチャンクされたデータで、サーバー側は次のチャンクを待つことを知らないので簡単ですか?

+0

**データはどれくらい大きいですか? – stuartd

+0

その文字列の長さはtbhです。 deserialisingなどの前にhttpのparamsを記録します(HttpContext.Request.Params.ToString())。したがって、失敗したリクエストの1つは117,454文字ですか? –

+0

また、このサイズのパラメータが3,119,214あることを確認しました。どちらが失敗しなかったのですか?だから私はサイズのために切り捨てを除外することができますか? –

答えて

0

いくつかのコメント、回答、および最終的には失敗したデータがありましたが、これを解決できました。

ユーザーが特殊文字を使用しただけでなく、送信された静的データの一部にこれが含まれていることが判明しました(GIGO - 私たちのデータの状態の一部を信じられませんでした)。

クライアント側溶液:

encodeURIComponentで()関数は、URIの成分をコードします。 この関数は特殊文字をエンコードします。さらに、次の文字をエンコードします。、/? :@ & = + $#

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

サーバーサイドソリューション:

は、そのアンエスケープされた表現に文字列を変換します。 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アプリケーションの構成:

私は20通の電子メールを送信しようとするため、500エラーを取得したユーザを、持っていました。私は、最大要求長(キロバイト、例は1GB)と最大コンテンツ長(バイトで、例は1GB)を含めるように設定を更新しました。電子メールは何の問題もありませんでした。それを信じられませんでした!

<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

使用しているjQueryのバージョンは指定していませんが、安定版と仮定した場合、ダウンラインで必要なエンコーディングとエスケープが完璧であることが確認できます。

要求の長さが原因であった場合、クライアント側でhttpエラーが発生し、サーバー側機能の呼び出し(「最大要求長を超えました」)が表示されます。これは、より長い文字列の要求は成功し、短いものは失敗するというあなたの見解によって支持されています。

は、私は2つのアクションをお勧めしたい:

1)だけテレメトリないJSONifyを行い、断片化、階層化し、可能な誤解を招く診断を減らすために。ランタイムクライアント側でtelemetry.JSONify()の値を点検)

2全体として(可能ならばその手段は、TelemetryMapping説明内のメタデータを含める)ことJSONify そして、テレメトリ、ユーザーIDとisMyViのうち、あなたのオブジェクトを構築。切り詰めがこれによって引き起こされることがわかった場合は、knockoutJSのバージョンと整合性に焦点を当てるか、または置き換えます。 @Destrifが彼らのコメントで指摘するように、https://stackoverflow.com/a/21565447/1132334は、二重引用符をエスケープするknockoutJSのタスクの一部ではないかもしれないことを示唆しているバックスラッシュとスラッシュ -

escape()に呼び出しをラップするような単純なものかもしれない:

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

JavaScriptバージョン1.5では、escape()関数は廃止されました。代わりに、encodeURI()またはencodeURIComponent()を使用してください。 –

1

実際に送信されるデータの概要を知るために、フィドラーを使用することをお勧めします。デシリアライゼーションの問題であり、コードは完全にうまく見えます。データのサイズはここでは問題ではないはずです。データの生のビューを取得しても問題ありません。

JSONify()が文字シーケンスをエスケープすることなく正しくフォーマットされたデータを返すかどうかも確認してください。

1

ユーザーが入力したコンテンツにencodeURIComponentを使用してみます。

関連する問題