WCF中因序列化問題引起的異常和錯誤。

2022-01-24 13:09:58 字數 3301 閱讀 3409

這段時間一直在忙著趕專案,由dal+wcf+winform幾層組成。其中資料庫使用的mysql+mysql.data.dll driver。不過在使用中,經常碰到如下錯誤:

接收對http://localhost/***.svc的 http 響應時發生錯誤。這可能是由於服務終結點繫結未使用 http 協議造成的。這還可能是由於伺服器中止了 http 請求上下文(可能由於服務關閉)所致。有關詳細資訊,請參見伺服器日誌。

有時也會出現如下錯誤

基礎連線已經關閉: 連線被意外關閉。
經過仔細核對發現,每當發生mysql.data.mysqlclient.mysqlexception異常時,就會報這個錯誤。網上找了半天也沒有找到解決方案,後來使用trace viewer跟蹤才發現是mysqlexception序列化時出現了問題:

system.servicemodel.communicationexception: 嘗試對引數進行序列化時出錯: result。innerexception 訊息是「不應為資料協定名稱為「mysqlexception:的型別「mysql.data.mysqlclient.mysqlexception」。請考慮使用datacontractresolver,或將任何未知型別以靜態方式新增到已知型別的列表。例如,可以使用 knowntypeattribute 特性,或者將未知型別新增到傳遞給 datacontractserializer 的已知型別列表。」。有關詳細資訊,請參見 innerexception。  system.runtime.serialization.serializationexception:.......

其中result是乙個儲存操作結果的類例項,它橫跨dal、wcf、winform三層,用以儲存乙個完整操作中發現的異常及資訊。裡面對可能發生的異常做了包裝,它的結構如下(其它屬性及建構函式等沒有列出):

public

class result

set
}
private exception exception;
[datamember]
publice exception exception
set
}
}

當dal層中涉及sql語句的執行發生錯誤時,result.exception型別實際為mysqlexception。雖然在result類定義時已經宣告[datacontract],不過序列化時仍然出錯,頭疼!檢視mysqlexception的定義如下:

public

sealed

class mysqlexception : dbexception

}

明明是已經宣告了[serializable]特性,而且檢視mysql.data.dll 文件,發現其在0.7版本的時候,就已經支援序列化了,卻仍然不可在wcf中序列化,只能再找原因。

根據錯誤的提示,在iservice的契約宣告介面中,加上了[serviceknowntype(typeof(mysql.data.mysqlclient.mysqlexception))]宣告,可到頭來結果還是一樣不起作用。但是如果發生的異常不是mysqlexception型別時,就不會報序列化錯誤。

對比exception和mysqlexception的實現,發現雖然都宣告了[serializable]特性,但mysqlexception卻沒有實現序列化和逆序列化的函式。問題很可能出現在這個地方。

不過由於沒有mysql.data.dll 的源**,無法讓新增這兩個函式,只得新建乙個異常類customexception存放在result。其**如下:

public

class customexception : iserializable,exception

}
private

string stacktrace;

public

override

string stacktrace

}
public customexception()
public customexception(string exceptionmessage, string exceptionstacktrace)
/*
以下序列化和逆序列化中,只儲存了message和stacktrace
*/
protected customexception(serializationinfo info, streamingcontext context)
public

override

void getobjectdata(serializationinfo info, streamingcontext context)

public

override

string tostring()

}

之所以override定義message和stacktrace,是為能對它們倆重寫,因為exception類中,定義的stacktrace是唯讀的,message也只能在建構函式中賦值。此外,此處只定義了這兩個屬性,是因為專案中只用到了exception中的這兩個屬性,一般情況下,這兩個屬性也已經足夠查詢異常資訊了。

當然最主要的地方,還是要實現乙個建構函式,用來序列化,以及getobjectdata方法設定序列化物件的替代值。

再次跟蹤執行,當產生mysqlexception時,result物件可以正常從dal->wcf->winform。ok啦!

總結:這個問題,的確是折磨了我好幾天,由於是對wcf頭一次在專案中使用,對它的了解也不多。如果不是看到使用trace viewer,還不會找到問題的本質所在。看來.net下的異常提示,有時候也不一定就是問題的產生點,就像編譯**一樣,少個逗號,提示的資訊卻是五花八門。

反序列化異常問題

下面是一些複雜物件情況下一些總結 l 當父類繼承serializable介面,所有子類都可以被序列化 l 子類實現了serializable介面,父類沒有,父類中的屬性不能序列化 不報錯,資料會丟失 但是子類中屬性人能正確序列化 l 如果序列化的屬性是物件,這個物件也必須實現serializable...

Wcf序列化的迴圈引用問題1

1.wcf資料契約序列化,使用的類datacontractserializer 預設如果類不指定 datacontract 則序列化類的所有字段,並且在出現迴圈引用的時候回丟擲異常,服務終止 msdn文件說明 wcf 資料契約序列化使用 datacontractserializer 底層是xml序列...

序列化中的序列號衝突問題

一般序列化中的序列號衝突問題大致是這樣形成的 1.假設有乙個類user,實現了序列化介面 2.這個類編譯後形成乙個位元組碼檔案,由於實現了序列化介面,在編譯後的class檔案會帶有乙個序列 id,之後載入記憶體並建立物件等 3.然後我們通過物件輸出流把物件寫到乙個檔案裡,這時候序列號 id也會被寫入...