2009-04-23 46 views
14

Để trả lại thông tin hữu ích trong SoapException.Detail cho dịch vụ web asmx, tôi lấy ý tưởng từ WCF và tạo một lớp lỗi để chứa thông tin hữu ích cho biết. Đối tượng lỗi đó sau đó được tuần tự hóa theo yêu cầu XmlNode của số bị ném SoapException.Đối tượng tuần tự hóa thành XmlDocument

Tôi đang tự hỏi liệu tôi có mã tốt nhất để tạo ra các XmlDocument - đây là quan điểm của tôi về nó:

var xmlDocument = new XmlDocument(); 
var serializer = new XmlSerializer(typeof(T)); 
using (var stream = new MemoryStream()) 
{ 
    serializer.Serialize(stream, theObjectContainingUsefulInformation); 
    stream.Flush(); 
    stream.Seek(0, SeekOrigin.Begin); 

    xmlDocument.Load(stream); 
} 

Có cách nào tốt hơn để làm điều này?

UPDATE: Tôi thực sự đã kết thúc làm những điều sau đây, bởi vì trừ khi bạn quấn XML trong một phần tử <detail> xml, bạn nhận được một SoapHeaderException vào cuối khách hàng:

var serialiseToDocument = new XmlDocument(); 
var serializer = new XmlSerializer(typeof(T)); 
using (var stream = new MemoryStream()) 
{ 
    serializer.Serialize(stream, e.ExceptionContext); 
    stream.Flush(); 
    stream.Seek(0, SeekOrigin.Begin); 

    serialiseToDocument.Load(stream); 
} 

// Remove the xml declaration 
serialiseToDocument.RemoveChild(serialiseToDocument.FirstChild); 

// Memorise the node we want 
var serialisedNode = serialiseToDocument.FirstChild; 

// and wrap it in a <detail> element 
var rootNode = serialiseToDocument.CreateNode(XmlNodeType.Element, "detail", ""); 
rootNode.AppendChild(serialisedNode); 

UPDATE 2: Do Câu trả lời tuyệt vời của John Saunders, tôi đã bắt đầu sử dụng như sau:

private static void SerialiseFaultDetail() 
{ 
    var fault = new ServiceFault 
        { 
         Message = "Exception occurred", 
         ErrorCode = 1010 
        }; 

    // Serialise to the XML document 
    var detailDocument = new XmlDocument(); 
    var nav = detailDocument.CreateNavigator(); 

    if (nav != null) 
    { 
     using (XmlWriter writer = nav.AppendChild()) 
     { 
      var ser = new XmlSerializer(fault.GetType()); 
      ser.Serialize(writer, fault); 
     } 
    } 

    // Memorise and remove the element we want 
    XmlNode infoNode = detailDocument.FirstChild; 
    detailDocument.RemoveChild(infoNode); 

    // Move into a root <detail> element 
    var rootNode = detailDocument.AppendChild(detailDocument.CreateNode(XmlNodeType.Element, "detail", "")); 
    rootNode.AppendChild(infoNode); 

    Console.WriteLine(detailDocument.OuterXml); 
    Console.ReadKey(); 
} 
+0

Tôi đã cập nhật mã bưu điện cho phần tử chi tiết. –

+0

tổng thể nó có vẻ tốt với tôi, mặc dù tôi nghĩ rằng tôi muốn sử dụng các đối tượng gõ mạnh mẽ hơn là vars trong trường hợp này. Ngoài ra, tôi không biết rằng 'stream.Seak (0, SeekOrigin.Begin)' thực sự là cần thiết. – CodeMonkey1313

Trả lời

18

EDIT: Tạo ra outp ut bên trong phần tử chi tiết

public class MyFault 
{ 
    public int ErrorCode { get; set; } 
    public string ErrorMessage { get; set; } 
} 

public static XmlDocument SerializeFault() 
{ 
    var fault = new MyFault 
        { 
         ErrorCode = 1, 
         ErrorMessage = "This is an error" 
        }; 

    var faultDocument = new XmlDocument(); 
    var nav = faultDocument.CreateNavigator(); 
    using (var writer = nav.AppendChild()) 
    { 
     var ser = new XmlSerializer(fault.GetType()); 
     ser.Serialize(writer, fault); 
    } 

    var detailDocument = new XmlDocument(); 
    var detailElement = detailDocument.CreateElement(
     "exc", 
     SoapException.DetailElementName.Name, 
     SoapException.DetailElementName.Namespace); 
    detailDocument.AppendChild(detailElement); 
    detailElement.AppendChild(
     detailDocument.ImportNode(
      faultDocument.DocumentElement, true)); 
    return detailDocument; 
} 
+0

+1 để trở thành giải pháp thực sự gọn gàng. Tuy nhiên, cho rằng tôi cần bọc XML của đối tượng được tuần tự hóa vào phần tử gốc "", cách tiếp cận tốt nhất là gì? Tôi đã thử tạo một nút, sau đó sử dụng navigator của nút mới nhưng có một InvalidOperationException với "WriteStartDocument không thể được gọi trên các nhà văn được tạo ra với ConformanceLevel.Fragment." –

+0

Ahh, bây giờ tôi hiểu. Sử dụng giá trị trả về của ImportNode cho cuộc gọi AppendChild là liên kết trong chuỗi mà tôi đã bỏ lỡ. Tôi thực sự ghét những lớp XML lộn xộn này trong .net, tôi phải nói. Cảm ơn bạn đã giúp đỡ. –

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