2012-11-29 42 views
7

Chúng tôi có API REST, được xây dựng với WCF.Sai WebFaultXảy ra khi sử dụng Luồng và đóng luồng

Chúng tôi xử lý tất cả các trường hợp ngoại lệ phụ trợ với WebFaultException như thế này:

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

này hoạt động tốt, ngoại trừ trong một kịch bản mà chúng tôi làm một bài viết, với một dòng suối.

Một ví dụ về điều này:

[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); 

Khi xử lý luồng này trong một tuyên bố sử dụng, bất cứ khi nào thì chúng ta chạy vào một ngoại lệ, chúng tôi tiếp tục nhận được:

Từ Fiddler:

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> 

Có vẻ như nó có liên quan đến luồng và StreamRead er đang được xử lý.

Sau đó tôi đã cố gắng xóa mọi thứ sẽ xử lý StreamReader và tính năng này hoạt động. Mã xử lý này ngay bây giờ trông như thế này:

enter image description here

này giải quyết vấn đề với việc gửi tin nhắn ngoại lệ đúng, nhưng làm thế nào xấu này sẽ ảnh hưởng đến ứng dụng của chúng tôi, chứ không phải đóng cửa hoặc xử lý StreamReader của chúng tôi? Bạn có thấy cách giải quyết nào khác không?

Trả lời

7

Điều này xảy ra do StreamReader tiếp quản quyền sở hữu của luồng. Nói cách khác, nó tự chịu trách nhiệm đóng luồng nguồn. Ngay sau khi chương trình của bạn gọi Dispose hoặc Close (để lại phạm vi câu lệnh sử dụng trong trường hợp của bạn) thì nó cũng sẽ loại bỏ luồng nguồn. Gọi sr.Dispose() trong trường hợp của bạn. Vì vậy, luồng tệp đã chết sau đó.

Nếu bạn không muốn điều này, bạn có thể tạo một lớp mới kế thừa từ StreamReader và ghi đè phương thức Đóng; bên trong phương thức Close của bạn, gọi Dispose (false) không đóng luồng.

Bạn cũng có thể sử dụng lớp học NonClosingStreamWrapper từ thư viện MiscUtil của Jon Skeet, nó phục vụ chính xác mục đích đó.

Nhưng tốt hơn hết là không nên rời khỏi StreamReader mà không xử lý vì nó không thể xóa bất kỳ tài nguyên không được quản lý nào.

Các vấn đề liên quan