[英]JsonConvert.SerializeObject on an exception loses the message
以前從未見過,基本上我的 MSMQ 調用拋出訪問被拒絕,這在 Visual Studio 中顯示為( exception.ToString()
)
System.Messaging.MessageQueueException (0x80004005): 對消息隊列系統的訪問被拒絕。\\r\\n 在 System.Messaging.MessageQueue.MQCacheableInfo.get_WriteHandle()\\r\\n
在 System.Messaging.MessageQueue.StaleSafeSendMessage(MQPROPS 屬性,IntPtr 事務)\\r\\n 在 System.Messaging.MessageQueue.SendInternal(Object obj, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType)\\r\\n 在 redacted.d__2.MoveNext() 中c:\\path\\file.cs:line 24
現在,這會記錄到對包含我的日志記錄代碼的類庫的調用中。
我的代碼這樣做:
var logMessage = new LogEntry(applicationName, exception, message, level);
LogEntry
只是一個普通的舊類,它將這些東西放入屬性中,不做任何其他事情。
var logEntryAsJson = JsonConvert.SerializeObject(logMessage);
此行應將其序列化為 JSON。 但是,當它發生時,異常屬性更改為:
"Exception":{"NativeErrorCode":-1072824283,"ClassName":"System.Messaging.MessageQueueException","Message":"外部組件拋出異常。","Data":null,"InnerException":null, "HelpURL":null,"StackTraceString":" 在 System.Messaging.MessageQueue.MQCacheableInfo.get_WriteHandle()\\r\\n 在 System.Messaging.MessageQueue.StaleSafeSendMessage(MQPROPS 屬性,IntPtr 事務)\\r\\n 在 System.Messaging .MessageQueue.SendInternal(Object obj, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType)\\r\\n at redacted.d__2.MoveNext() in c:\\path\\file.cs:line 24","RemoteStackTraceString":null,"RemoteStackIndex": 0,"ExceptionMethod":"8\\nget_WriteHandle\\nSystem.Messaging, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\\nSystem.Messaging.MessageQueue+MQCacheableInfo\\nSystem.Messaging.Interop.MessageQueueHandle get_Write(Handle), HResult":-2147467259,"Source":"System.Messaging","WatsonBuckets":null}
將鼠標懸停在序列化行上的 logMessage 對象上的智能感知顯示第一個異常數據。 但是當序列化時,它完全改變了它。 結果,錯誤的原因沒有被記錄下來,所以我在嘗試調試它的時候撓了撓頭。
這種行為有原因嗎? 我是否必須強制將異常存儲為字符串?
Exception
類實現 ISerializable。 Json.NET 認識到這一點,並且只序列化類本身指定的屬性。 正如文檔解釋的那樣:
可序列化
實現 ISerializable 並用 SerializableAttribute 標記的類型被序列化為 JSON 對象。 序列化時,只使用 ISerializable.GetObjectData 返回的值; 類型的成員被忽略。 反序列化時,將調用具有 SerializationInfo 和 StreamingContext 的構造函數,傳遞 JSON 對象的值。
在不需要此行為的情況下,可以將 JsonObjectAttribute 放在實現 ISerializable 的 .NET 類型上,以強制將其序列化為普通 JSON 對象。
MessageQueueException.Message屬性在運行時計算,並從 .NET 運行時的資源加載一個字符串。 它不會被 GetObjectData 保存,因為實際文本既不需要也不想要——當在另一個系統上反序列化時, Message
將返回該系統可用的本地化字符串。
External component has thrown an exception
來自父ExternalException類External component has thrown an exception
,該類在Message
存儲一個字符串但不覆蓋GetObjectData
。
這對於序列化和反序列化來說不是問題,因為數據足以再水合正確的對象。 不過,這是 JSON 的一個問題,它不包含類型信息。
可以禁用此行為。 一種方法是向類添加屬性,這在 BCL 類中是不可能的。 另一種可能性是使用忽略 ISerializable 的 合同解析器。 DefaultContractResolver 具有類似IgnoreSerializableInterface 的屬性:
string json =
JsonConvert.SerializeObject(
exception,
Formatting.Indented,
new JsonSerializerSettings {
ContractResolver = new DefaultContractRresolver {
IgnoreSerializableInterface=true
}}
);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.