2010-02-12 28 views
6

Trong lớp khách hàng WCF của tôi, tôi đang xử lý sự kiện Faulted() để nếu dịch vụ từ xa ném một ngoại lệ và lỗi thì kênh tôi vẫn có thể tắt ít nhất một cách duyên dáng. Dưới đây là mã của tôi:System.ServiceModel.Diagnostics.CallbackException là gì và tại sao tôi không thể xử lý nó?

protected void RemoteDataRetriever_Faulted(object sender, EventArgs e) 
{ 
    (sender as ICommunicationObject).Abort(); 
    this.Dispose(); 
    throw new ChannelTerminatedException("The remote service threw an unhandled exception and as a result the channel has been closed."); 
} 

Vì vậy, những gì tôi mong đợi là các khách hàng có thể xử lý các ChannelTerminatedException mà tôi đã ném bằng tay và gửi một thông điệp tới người sử dụng, vv Thay vì ngoại lệ của tôi là nhận được bọc trong một System.ServiceModel.Diagnostics.CallbackException. Ok, được rồi. Ngoại trừ đây là bắt: CallbackException này không tồn tại trong thư viện ServiceModel và dường như không có cách nào để tôi xử lý nó ngoại trừ một số chung chung Exception, điều này làm tôi không tốt cho các bài kiểm tra đơn vị của mình. Cái quái gì đang xảy ra ở đây? Tôi có thể vô hiệu hóa bằng cách nào đó và ném ngoại lệ mà ban đầu tôi muốn không?

+0

Vì bạn đang tự ném ngoại lệ, bạn có thể sử dụng một ngoại lệ khác không bị gói không? Tôi đang suy nghĩ một cái gì đó mà không phơi bày thực tế là bạn đang sử dụng WCF bên dưới tất cả ... –

+0

Không có súc sắc. Tôi đã thay đổi ChannelTerminatedException thành một StackOverflowException ;-) và nó vẫn nhận được gói trong đó CallbackException gây phiền nhiễu (một trong tôi ném kết thúc lên là ngoại lệ bên trong). Và sau đó nó đưa ra thông điệp gây phiền nhiễu: "Một cuộc gọi lại của người dùng đã ném một ngoại lệ. Kiểm tra ngăn xếp ngoại lệ và ngoại lệ bên trong để xác định cuộc gọi lại không thành công". Có, tôi biết gọi lại đã ném một ngoại lệ! Tôi là người đã ném nó! Tôi sẽ làm nghiên cứu nhiều hơn và xem nếu có một cờ WCF/tham số một nơi nào đó mà tôi có thể sử dụng để vô hiệu hóa hành vi này. –

Trả lời

4

Khi nó quay ra, System.ServiceModel.Diagnostics.CallbackException là một lớp bên trong được nhồi nhét bên trong một cụm được gọi là "% SystemRoot% \ Microsoft.net \ Framework \ v3.0 \ Windows Communication Foundation \ SMDiagnostics.dll", bản thân nó chỉ chứa nội bộ các lớp học. Vâng, đó là stinks bởi vì nó có nghĩa là chúng tôi không bao giờ có thể, bao giờ bắt ngoại lệ đó. Tuy nhiên, tôi đã có thể truy tìm lớp/phương thức khởi tạo ngoại lệ trên (System.ServiceModel.Diagnostics.ExceptionUtility.ThrowHelperCallback (Ngoại lệ innerException)) và thấy rằng nó đang được gọi bằng phương thức ảo OnFaulted() bên trong CommunicationObject. Vì vậy, về mặt lý thuyết, bất kỳ lớp nào xuất phát từ CommunicationObject (xin lỗi ClientBase<T>) có thể ghi đè phương thức đó và yêu cầu nó không gọi ThrowHelperCallback(). Điều này có nghĩa là các ứng viên khả thi duy nhất là các lớp học lấy từ ChannelFactoryBase<T>. Về lý thuyết, tôi có thể tiếp tục và triển khai nhà máy sản xuất kênh tùy chỉnh của riêng mình để ngăn chặn CallbackException gây phiền nhiễu nhưng hiện tại nó quá nhiều công việc nên tôi đoán tôi sẽ phải giải quyết nó.

EDIT: @Jeremy - Nếu tôi kiểm tra phong bì SOAP quay lại trên dây, tôi thấy rằng nó mang lại cho tôi lỗi chung, như mong đợi, cho biết rằng CallbackException KHÔNG được đăng và do đó KHÔNG được tạo máy chủ.

<s:Body> 
    <s:Fault> 
     <s:Code> 
      <s:Value>s:Receiver</s:Value> 
      <s:Subcode> 
       <s:Value xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</s:Value> 
      </s:Subcode> 
     </s:Code> 
     <s:Reason> 
      <s:Text xml:lang="en-US">The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the &lt;serviceDebug&gt; configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.</s:Text> 
     </s:Reason> 
    </s:Fault> 
</s:Body> 
+0

Tôi không nghĩ rằng tôi làm rõ rằng CallbackException được tạo ra trên máy khách như là một phản ứng với một ngoại lệ unhandled trả về bởi máy chủ. Điểm chính của tôi là lỗi chung nên được xử lý phía máy chủ để khách hàng (mà có thể rất tốt được xây dựng bởi một người nào đó trong ngôn ngữ khác) không phải. –

+0

OK, +1 cho câu trả lời của bạn.Trong trả lời, tôi đang sử dụng FaultContracts để gửi qua các trường hợp ngoại lệ phổ biến nhất để được xử lý một cách duyên dáng trên đầu khách hàng nhưng ngoại lệ nghiêm trọng và bất ngờ hơn sẽ được xử lý trong sự kiện Faulted lý tưởng. Đó là lý do tại sao tôi hơi buồn với MS rằng họ ăn cắp ngoại lệ mà tôi đang cố gắng ném và bọc nó trong một lớp học bên trong họ. Tuy nhiên, đã phát triển cho một số ít các khuôn khổ MS bây giờ tôi biết rằng đây chỉ là mệnh cho khóa học. –

+0

Cách xử lý ngoại lệ là một trong những thứ mà mọi người có cách làm khác nhau, nhưng tôi đồng ý rằng không có nghĩa là ném một ngoại lệ không thể tiếp cận, ngay cả khi phương thức ném nó được dự định sẽ bị ghi đè. Ít nhất quấn nó trong một loại công cộng để nó có thể được xử lý. –

2

Bạn đang thấy System.ServiceModel.Diagnostics.CallbackException vì ngoại lệ xảy ra trên máy chủ. Khi ngoại lệ xảy ra bên ngoài miền của ứng dụng khách, nó có thể là kiểu mà máy khách không có quyền truy cập. Cơ chế gọi lại xử lý việc này bằng cách tạo ra CallbackException mà bạn đang thấy. Điều này tương tự như System.TypeInitializationException bị ném khi một ngoại lệ chưa được xử lý xảy ra khi truy cập một thành viên tĩnh. Nếu bạn đang cố gắng xử lý điều này một cách duyên dáng, bạn có thể muốn xử lý ngoại lệ ở phía máy chủ và đóng socket, sau đó sẽ kích hoạt một ngoại lệ trên máy khách có thể được xử lý.

+0

Không đúng. Xem câu trả lời của tôi. –

+0

Tôi nghĩ rằng cách tôi phrased nó là một chút mơ hồ. Tôi đã chỉnh sửa câu trả lời để có một chút rõ ràng hơn. –

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