Serialize object to XmlDocument

W celu zwrócenia użytecznych informacji w SoapException.Detail dla usługi internetowej asmx, wziąłem pomysł z WCF i stworzyłem klasę błędów, która zawierałaby te przydatne informacje. Ten obiekt błędu jest następnie serializowany do wymaganego XmlNode rzuconego SoapException.

Zastanawiam się czy mam najlepszy kod do stworzenia {[6] } - Oto moje zdanie na ten temat:

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);
}
Czy jest na to lepszy sposób?

UPDATE: W sumie zrobiłem co następuje, bo chyba że zawijasz XML w elemencie <detail> XML, otrzymasz SoapHeaderException na końcu klienta:

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: biorąc pod uwagę doskonałą odpowiedź Johna Saundersa, zacząłem teraz używać następującego:

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();
}
Author: Soviut, 2009-04-23

1 answers

EDIT: tworzy wyjście wewnątrz elementu detail

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;
}
 19
Author: John Saunders,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-23 18:14:08