2012-11-29 22 views
7

WCFで構築されたREST APIがあります。ストリームを使用してストリームを閉じるときにWebFaultExceptionが発生する

throw new WebFaultException<string>(e.Message, HttpStatusCode.NotAcceptable); 

これは、我々はストリームと、ポストを行う1つのシナリオ以外ではうまく動作します:

私たちは、すべての例外は、このようWebFaultExceptionとバックエンド処理します。

本の例:

[WebInvoke(Method = "POST", UriTemplate = "saveUser?sessionId={sessionId}&userId={userId}", 
     RequestFormat = WebMessageFormat.Json, 
     ResponseFormat = WebMessageFormat.Json,    
     BodyStyle = WebMessageBodyStyle.WrappedRequest)] 
    [OperationContract] 
    string SaveUser(string sessionId, int userId, Stream stream); 

我々は、我々は得続ける例外に遭遇したときに、usingステートメントで、このストリームを扱う:フィドラーから

HTTP/1.1 400 Bad Request 
    <p>The server encountered an error processing the request. The exception message is 'The message object has been disposed.'. See server logs for more details. The exception stack trace is: </p> 
    <p> at System.ServiceModel.Channels.ByteStreamMessage.InternalByteStreamMessage.get_Properties() 
    at System.ServiceModel.OperationContext.get_IncomingMessageProperties() 
    at System.ServiceModel.Dispatcher.WebErrorHandler.ProvideFault(Exception error, MessageVersion version, Message&amp; fault)</p> 

ストリームとStreamReadとは関係がありますそれは処分される。

その後、StreamReaderを処理するものを削除しようとしましたが、この機能は有効です。

enter image description here

これは正しい例外メッセージを送信して問題を解決しますが、どのように悪いこれは、閉じたり、私たちのStreamReaderを配置していない、我々のアプリケーションに影響します。今、これを処理するコードは次のようになりますか? これを解決する他の方法がありますか?

答えて

7

これは、StreamReaderがストリームの所有権を引き継ぐためです。言い換えれば、ソースストリームをクローズする役割を果たします。あなたのプログラムがDisposeまたはClose(あなたのケースでusingステートメントスコープを残す)を呼び出すとすぐに、それはソースストリームも破棄します。あなたのケースではsr.Dispose()を呼び出します。したがって、ファイルストリームは死んでしまいました。

これを望まない場合は、StreamReaderから継承して、Closeメソッドをオーバーライドする新しいクラスを作成できます。 Closeメソッドの中で、ストリームを閉じないDispose(false)を呼び出します。

また、Jon SkeetのMiscUtilライブラリのNonClosingStreamWrapperクラスを使用することもできます。これは、その目的と同じです。

ただし、管理されていないリソースをクリーニングできないため、廃棄せずにStreamReaderを終了しない方がよいでしょう。

関連する問題