當試圖反序列化從jQuery.ajax()發送的JSON數據時,我在我的(C#)服務器代碼中偶爾出現異常。 POST數據完全是NULL字符(二進制,0x00)。我記錄在我的日誌,並在文本模式錯誤的所有POST數據,它看起來像位:爲什麼IE6發送NULL字符(0x00)作爲JSON POST數據?
" "
但在二進制模式,它是:
00 00 00 00 00 00 00 00 00 00
此完全相同的錯誤已被記錄3次,來自同一用戶,大約相隔15分鐘。
可能會發生什麼?我谷歌搜索,沒有發現這樣的事情。
下面是來自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
另一條線索:在我們的全局錯誤處理程序,我們嘗試寫一個響應消息給用戶(比如「抱歉,你有問題,我們正在研究它」)。當我們試圖對這個用戶做到這一點,每次我們有同樣的異常:
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(),它會一直效率稍差一點,但從來沒有這個錯誤。
你是如何獲取數據到你的C#?通常這樣的錯誤是通過使用陣列或MemoryStream的還沒有被完全填充(例如,由於客戶端發送較少的數據比預期的)導致的。 – EricLaw
@EricLaw好點!我已經添加了我的數據閱讀代碼。 – Yoshi
閱讀過我自己的代碼,我真的應該使用Request.ContentEncoding而不是UTF8。這可能會導致這個問題嗎?我假設舊版瀏覽器會發送ASCII +擴展的代碼頁字符,UTF8會將其解碼爲gobbledygook而不是NULL。 – Yoshi