0

jQuery.ajax() から送信された JSON データを逆シリアル化しようとすると、(C#) サーバー コードで時折例外が発生します。POST データは完全に NULL 文字です (バイナリで 0x00)。エラーからのすべての POST データをログに記録し、テキスト モードで記録します。スペースのように見えます。

"          "

ただし、バイナリ モードでは次のようになります。

00 00 00 00 00 00 00 00 00 00

このまったく同じエラーが、同じユーザーから約 15 分間隔で 3 回ログに記録されています。

何が起こっているのでしょうか?私はグーグルで検索しましたが、このようなものは何も見つかりませんでした。

JSON デシリアライザーからの実際のエラーは次のとおりです。

System.ArgumentException:  Invalid JSON primitive: .
    at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializePrimitiveObject()
    at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)
    at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input, Int32 depthLimit, JavaScriptSerializer serializer)
    at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)

ユーザーエージェント:

Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; MS-RTC LM 8; InfoPath.2)

コンテンツ タイプ:

application/json

もう 1 つの手がかり: グローバル エラー ハンドラーで、ユーザーに応答メッセージを書き込もうとします (「問題が発生して申し訳ありません。調査中です。」など)。このユーザーに対してこれを実行しようとすると、毎回同じ例外が発生しました。

System.Web.HttpException (0x80070057): The remote host closed the connection. The error code is 0x80070057.
    at System.Web.Hosting.IIS7WorkerRequest.RaiseCommunicationError(Int32 result, Boolean throwOnDisconnect)
    at System.Web.Hosting.IIS7WorkerRequest.ExplicitFlush()
    at System.Web.HttpResponse.Flush(Boolean finalFlush)
    at System.Web.HttpResponse.End()

データを読み取る方法は次のとおりです (ライブラリ コードの一部をコピーして貼り付ける必要がありました)。

[Ajax]
[AsyncTimeout(300001)] // 5 minutes
[ValidateInput(false)] // We want to pass in XML via POST
public void CommandAsync()
{
    AsyncManager.OutstandingOperations.Increment();

    // Reads the main body of a request, without closing the
    // stream.  The advantage of not closing the stream is that it can
    // be re-read later, particularly by the Global.asax.cs error
    // handler.
    // It seems that if the content type is not form-url-encoded
    // then the input stream needs to be reset.  Weird.
    Request.InputStream.Position = 0;
    byte[] content = new byte[Request.ContentLength];
    Request.InputStream.Read(content, 0, Request.ContentLength);
    string dataStr = Encoding.UTF8.GetString(content);

    if (dataStr.Length != 0) {
        var data = serializer.Deserialize<Dictionary<string, object>>(dataStr);

        // do something with data
    }
}

[編集]

Eric は、IE がストリームでデータを送信しなかったという点で正しかった。

したがって、私たちにとっての解決策は、読み取られたものに配列を縮小することです。

    int content_length = request.ContentLength;
    byte[] content = new byte[content_length];
    int read = request.InputStream.Read(content, 0, content_length);
    if (read < content_length)
        Array.Resize(ref content, read);

あるいは、単純に StreamReader(request.InputStream).ReadToEnd() を使用することもできました。その場合、効率は少し悪くなりますが、このバグは発生しませんでした。

4

1 に答える 1

1

ありがとうエリック、あなたは正しかった!

AJAX ポスト リクエストが Internet Explorer でキャンセルされた場合でも、サーバーに送信されますが、実際のコンテンツがなく、ヘッダーのコンテンツの長さが正しくありませんでした。

以下を使用してコンテンツを読み取ります。

request.InputStream.Position = 0;
byte[] content = new byte[request.ContentLength];
request.InputStream.Read(content, 0, request.ContentLength);

初期化された配列を上書きするコンテンツがなかったため、\0 のバイト配列が作成されました。

于 2013-08-22T03:24:58.093 に答える