簡體   English   中英

異常上的 JsonConvert.SerializeObject 丟失消息

[英]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來自父ExternalExceptionExternal 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM