wcf tips之三
wcf支援對stream物件的操作,尤其對於傳遞size過大的訊息而言,如要考慮傳遞訊息的效率,wcf推薦通過stream進行操作。
然而,wcf對於stream操作規定了一些限制,在我們編寫相關程式時,需要特別注意:
1、繫結的限制
如果需要使用stream操作,可以使用的繫結只能是basichttpbinding,nettcpbinding以及netnamedpipebinding。此外,在使用stream操作時,不能使用reliable messaging。如果考慮到訊息安全,則此方式是不可取的。
2、對stream物件的限制
要作為服務操作所傳遞的訊息物件,這樣的物件必須是可序列化的。遺憾的是,filestream類的定義卻是不支援序列化的,我們能夠使用的stream物件,包括stream,memorystream等。使用stream類物件是大多數stream操作的首選。
乙個有趣的現象是filestream與stream型別的轉換。例如在服務契約的操作中,有如下的實現:
public
stream transferdocument(document document)
注意,操作transferdocument()的返回型別為stream,而方法的實現中,返回的物件則為filestream型別。由於stream類是filestream類的父類,這樣的實現沒有問題。
然而,在客戶端呼叫該操作時,卻不能將操作的返回值賦給filestream型別的物件,如下所示:
filestream stream
=m_service.transferdocument(doc);
此時獲得的stream物件則為null。因而,我們只能這樣呼叫操作:
stream stream
=m_service.transferdocument(doc);
但是,還有乙個奇怪的問題是wcf並不支援stream物件length屬性的序列化,也就是說,在客戶端我們不能使用服務操作返回的stream物件的length屬性。諸如stream.length的呼叫會丟擲notsupportedexception異常。
3、transfermode的限制
若要使用stream操作,必須修改繫結的transfermode屬性。該屬性的預設值為buffered。我們應該根據操作中stream物件的引數型別,以決定transfermode的值分別為streamed、streamedrequest或者streamedresponse。
4、maxreceivedmessagesize的限制
maxreceivedmessagesize屬性的預設值為64kb,如果傳遞的stream物件一旦超過了maxreceivedmessagesize屬性的設定值,則客戶端在操作該物件時,就會出現communicationexception異常。因此,我們應根據實際需要設定maxreceivedmessagesize的值。maxreceivedmessagesize屬性的取值範圍為1-9223372036854775807(int32.maxvalue)。如果設定值不在該範圍之內,則無法通過編譯。程式設計方式設定為:
binding.maxreceivedmessagesize
=120000
;配置檔案的設定方式為:
<
binding …… maxreceivedmessagesize="
120000
"/>
5、操作引數的限制
wcf對包含了stream物件的操作引數進行嚴格的限制,它只允許這樣的操作只能包含乙個stream物件,這裡所謂的乙個stream物件,是包含return物件,out和ref物件在內的。也就是說如下的操作定義都是錯誤的:
void
transfer(stream s1, stream s2);
void
transfer(stream s1,
outstream s2);
void
transfer(stream s1,
refstream s2);
stream transfer(stream stream);
如果定義了這樣的操作,則會出現執行時錯誤。
6、例項啟用型別的限制
由於stream操作受到繫結的限制,只能使用basichttpbinding,nettcpbinding以及netnamedpipebinding繫結,因此必然會影響服務例項的啟用型別,最主要的是對session模式的影響。首先basichttpbinding並不支援session模式的啟用型別。nettcpbinding以及netnamedpipebinding繫結雖然支援session模式,但是由於stream操作不支援可靠訊息傳遞,即不能將reliablesession設定為true。因此在定義服務契約的sessionmode時,不能將其值設定為sessionmode.required,否則會丟擲異常。
實際上,stream操作(指transfermode不為buffered)本身並不支援session模式。即使我們在使用nettcpbinding時,將服務契約的sessionmode設定為allowed,並將服務的instancecontextmode設定為persession,服務的執行方式仍然是percall方式。(如果不是stream操作,這樣的設定服務應為persession模式)
因此,在執行stream操作時,即使按照session模式對服務進行設定,如果我們通過operationcontext.current.sessionid去獲得會話id,其值應該為空。
此外,由於傳輸的stream物件較大,可能會消耗過長的時間,因而建議增大繫結的sendtimeout屬性值。例如設定為10分鐘。程式設計方式設定為:
binding.sendtimeout
=timespan.fromminutes(
10);
配置檔案的設定方式為:
<
binding …… sendtimeout="
00:10:00
"/>
注意,對繫結的相關設定必須要求服務端與客戶端的配置一致。最佳實踐是均通過配置檔案進行設定。例如在我的應用程式中是這樣設定的:
WCF中的Stream操作
wcf支援對stream物件的操作,尤其對於傳遞size過大的訊息而言,如要考慮傳遞訊息的效率,wcf推薦通過stream進行操作。然而,wcf對於stream操作規定了一些限制,在我們編寫相關程式時,需要特別注意 1 繫結的限制 如果需要使用stream操作,可以使用的繫結只能是basichttp...
WCF中的Stream操作
wcf支援對stream物件的操作,尤其對於傳遞size過大的訊息而言,如要考慮傳遞訊息的效率,wcf推薦通過stream進行操作。然而,wcf對於stream操作規定了一些限制,在我們編寫相關程式時,需要特別注意 1 繫結的限制 如 果需要使用stream操作,可以使用的繫結只能是basichtt...
WCF中的Stream操作
wcf支援對stream物件的操作,尤其對於傳遞size過大的訊息而言,如要考慮傳遞訊息的效率,wcf推薦通過stream進行操作。然而,wcf對於stream操作規定了一些限制,在我們編寫相關程式時,需要特別注意 1 繫結的限制 如 果需要使用stream操作,可以使用的繫結只能是basichtt...