2012-01-17 24 views
5

Tôi có một dịch vụ web asp.net (không phải WCF nhưng dịch vụ web .asmx cổ điển với WebMethods) ném các ngoại lệ. Tất cả các trường hợp ngoại lệ được lấy từ một trong hai loại ngoại lệ cơ bản (cả hai loại xuất phát từ Ngoại lệ):Tôi làm cách nào để xác định loại ngoại lệ được dịch vụ web asp.net đưa ra?

public class InputException : Exception 
{ 
    .... 
} 

public class FatalException : Exception 
{ 
    .... 
} 

public class NoFilesFound: FatalException 
{ 
    .... 
} 

.... 

Webservice ngay bây giờ ném ngoại lệ khi cần. Trong mã khách hàng của tôi, tôi có thể bắt các ngoại lệ và thấy thông báo như thế này:

Server was unable to process request. ---> There were no files found

Tuy nhiên, ngoại lệ là loại FaultException (như khi tôi làm .GetType() trên các ngoại lệ bắt). Trình khách gọi cần có khả năng phân biệt giữa một InputException và một FatalException (và tối ưu sự khác biệt giữa các cá thể có nguồn gốc riêng lẻ nhưng điều đó không quan trọng). Ngay bây giờ, cách duy nhất để làm như vậy là phân tích cú pháp thư, tách văn bản trước "--->" và bật văn bản. Điều đó rõ ràng là không tối ưu.

Tôi biết tôi có thể ném SoapExceptions bằng Mã tùy chỉnh nhưng tôi muốn tránh điều đó nếu có thể. Hơn nữa, nó có vẻ được thiết kế cho những người xử lý XML nhưng tất cả mã webservice của chúng tôi không chạm vào XML vì nó đã được deserialized cho chúng tôi rồi.

Vì vậy, trong ngắn hạn, có cách nào để tôi ném ngoại lệ tùy chỉnh từ webservice và cho ứng dụng khách gọi để có thể phân biệt giữa các ngoại lệ không?

Trả lời

7

Cách thích hợp để xử lý việc này là sử dụng SoapException. Vì vậy, về cơ bản bạn sẽ nắm bắt tất cả các ngoại lệ có thể có trên dịch vụ và sau đó dịch chúng sang SoapException (tài liệu tôi đã liên kết để chứa ví dụ) và sau đó thay vì ném một số ngoại lệ tùy chỉnh của bạn, hãy ném SoapException này và bao gồm thông tin bạn quan tâm nút XML chi tiết của lỗi.

Sau đó, khi gọi dịch vụ trên máy khách, bạn sẽ có thể nắm bắt SoapException này và phân tích nút Chi tiết XML để thu thập thêm chi tiết về nguyên nhân chính xác của lỗi xảy ra trên máy chủ.

Tất cả các thế hệ thủ công của các nút lỗi này đã được hiển thị rất dễ dàng trong WCF, nơi bạn chỉ cần làm việc với các hợp đồng dữ liệu và bắt FaultException<SomeFaultContract>.

Hãy lấy một ví dụ. Giả sử bạn có phương pháp dịch vụ sau đó ném một SoapException và cung cấp thông tin chi tiết về lỗi trong nút Details:

[WebMethod] 
public string HelloWorld() 
{ 
    var doc = new XmlDocument(); 
    var node = doc.CreateNode(
     XmlNodeType.Element, 
     SoapException.DetailElementName.Name, 
     SoapException.DetailElementName.Namespace 
    ); 
    // you could actually use any sub nodes here 
    // and pass even complex objects 
    node.InnerText = "no files found"; 

    throw new SoapException(
     "Fault occurred", 
     SoapException.ClientFaultCode, 
     Context.Request.Url.AbsoluteUri, 
     node 
    ); 
} 

khi tiêu thụ nó, bạn có thể bắt cho SoapException này trên máy khách:

using (var client = new WebService1()) 
{ 
    try 
    { 
     var result = client.HelloWorld(); 
    } 
    catch (SoapException ex) 
    { 
     var detail = ex.Detail; 
     // detail.InnerText will contain the detail message 
     // as detail is an XmlNode if on the server you have 
     // provided a complex XML you would be able to fetch it here 
    } 
} 

Như xa như các trường hợp ngoại lệ InputException, FatalExceptionNoFilesFound của bạn có liên quan, chúng vẫn ổn, nhưng chúng vẫn ở trên máy chủ. Nắm bắt chúng trong phương thức web của bạn và xây dựng một SoapException thích hợp mà khách hàng sẽ có thể hiểu được khi sử dụng dịch vụ.

+0

Cảm ơn bạn! Tôi sẽ tự hỏi nếu tôi có thể làm cho các lớp tùy chỉnh của tôi bắt nguồn từ SoapException và sau đó sử dụng constructor để xây dựng các XmlNodes ... – user1079591

+0

@ user1079591, vâng, bạn có thể và nó thực sự là một cách rất tốt để tiến hành. –

+0

Vì vậy, tôi đã làm như bạn đề nghị nhưng trong mã khách hàng nó không bắt nó như một SoapException mà là một System.ServiceModel.FaultException. Trong mã của tôi, tôi có hai khối catch: một cho SoapException và một cho ngoại lệ thường xuyên và nó luôn luôn đi đến ngoại lệ thường xuyên và khi tôi làm một.GetType() trên một generic nó nói nó là loại System.ServiceModel.FaultException. – user1079591

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