2009-04-23 11 views
14

SoapException.Detailで有用な情報をasmx Webサービスに返すために、私はWCFからアイデアを取り、前記有用な情報を含むためにフォールトクラスを作成しました。その障害オブジェクトは、次に、SoapExceptionが投げられたXmlNodeにシリアル化されます。オブジェクトをXmlDocumentにシリアル化

私はXmlDocumentを作成するための最良のコードを持っているかどうかを思ったんだけど - ここではそれが私の感想です:

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

は、これを行うのより良い方法はありますか?

UPDATE:あなたは<detail> xml要素にXMLをラップしない限り、あなたはクライアント側でSoapHeaderExceptionを取得するので、私は実際には、次のことをやってしまった:

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:を考えますジョン・サンダース優秀な答えは、私は今、次の使用を開始しました:

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

詳細要素のポストコードを更新しました。 –

+0

全体的には私には良く見えますが、この場合はvarsではなく強く型付けされたオブジェクトを使用すると思います。また、 'stream.Seak(0、SeekOrigin.Begin)'が本当に必要なのか分かりません。 – CodeMonkey1313

答えて

18

EDIT:OUTP作成しますut内の詳細要素

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は本当にきれいな解決策です。しかし、直列化されたオブジェクトのXMLをルート ""要素にラップする必要があることを考えれば、最良のアプローチは何ですか?私はノードの作成を試みた後、新しいノードのナビゲータを使用しましたが、 "WriteStartDocumentはConformanceLevel.Fragmentで作成されたライターでは呼び出せません"というInvalidOperationExceptionを取得しました。 –

+0

ああ、今私は理解している。 AppendChild呼び出しにImportNodeの戻り値を使用すると、チェーン内のリンクが失われていました。私は本当にネットでこれらの面倒なXMLクラスが嫌い、私は言う必要があります。ご協力いただきありがとうございます。 –