I'm trying to serialize objects to XML. I'm having an issue that xsi and xsd are being added by default. I added the following code to remove the namespaces:
public string CommitDocumentToRepository(string extension, byte[] fileBytes)
{
//Convert to PDF
byte[] loPDFFileBytes;
ConversionService.ContentResponse loResponse = new DocumentAdapter.ConversionService.ContentResponse();
using (ConversionService.CustomPDFSoapClient loConversionServiceClient = new DocumentAdapter.ConversionService.CustomPDFSoapClient())
{
loResponse = loConversionServiceClient.OfficeToPDFContent(fileBytes, extension);
loPDFFileBytes = loResponse.ContentPDF;
}
if (loPDFFileBytes != null)
{
xform loDocContainer = new xform();
xformInstance loDocProperties = new xformInstance();
loDocProperties.FIRST_NAME= this.FirstName;
loDocProperties.LAST_NAME= this.LastName;
loDocProperties.MID_NAME = this.MidName;
loDocContainer.instance = loDocProperties;
string lsTempFile = System.IO.Path.GetTempFileName();
string lsXMLofProperties = loDocContainer.Serialize();
XmlDocument loDoc = new XmlDocument();
loDoc.LoadXml(lsXMLofProperties);
loDoc.Save(lsTempFile);
byte[] loFilePropertiesXML = Common.StreamFile(lsTempFile);
string lsReturnValue = string.Empty;
try
{
using (ISCommittalService.CommittalSoapClient loCommittalServiceClient = new DocumentAdapter.ISCommittalService.CommittalSoapClient())
{
lsReturnValue = loCommittalServiceClient.CommitDocumentByte(loPDFFileBytes, ".PDF", loFilePropertiesXML);
}
}
catch (Exception loException)
{
ADConnectionException loConnectionException = new ADConnectionException(loException);
throw loException;
}
return lsReturnValue;
}
else
return string.Empty;
}
public string Serialize()
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
xws.Encoding = Encoding.UTF8;
StringBuilder loBuilder = new StringBuilder();
XmlSerializer formatter = new XmlSerializer(this.GetType());
using (StringWriter loWriter = new StringWriter(loBuilder))
{
formatter.Serialize(loWriter, this,ns);
}
return loBuilder.ToString();
}
This is the output:
<?xml version="1.0" encoding="UTF-16"?>
<xform>
<instance>
<FIRST_NAME xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance"
d3p1:type="q4:string"
xmlns:q4="http://www.w3.org/2001/XMLSchema">John</FIRST_NAME>
<MID_NAME xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance"
d3p1:type="q3:string" xmlns:q3="http://www.w3.org/2001/XMLSchema"/>
<LAST_NAME xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance"
d3p1:type="q5:string"
xmlns:q5="http://www.w3.org/2001/XMLSchema">Doe</LAST_NAME>
</instance>
</xform>
How can I remove that added xmlns (xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance"
d3p1:type="q4:string"
xmlns:q4="http://www.w3.org/2001/XMLSchema") from each object?
and how can I change it to utf-8 because xws.Encoding = Encoding.UTF8; that is my code seems doesn't have any affect.
Related
The company receives a form of XML files and stores them on an S3 bucket, the information is then shown on a customers website.
Issue I am having is they have onboarded a new customer with a new feed. The customers feed which they are now sending me are correct, Although their XML files are missing the declaration at the top.
Example of Declaration missing
<?xml version="1.0" encoding="UTF-8"?>
This is stopping the feed from processing and displaying on the website.
If I manually add the Declaration and re upload it works.
Now the customer is saying they have never had the headers and it works for other 3rd party companies.
Is there a way to add the header once receiving the files, the feed processor & FTP server are in c#, dotnet3.1
public static T Deserialize<T>(XmlReader reader)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty, new XmlQualifiedName("xs", "http://www.w3.org/2001/XMLSchema") });
object retVal = null;
XmlSerializer serializer = new XmlSerializer(typeof(T));
var settings = new XmlReaderSettings();
settings.IgnoreComments = true;
settings.ConformanceLevel = ConformanceLevel.Document;
settings.DtdProcessing = DtdProcessing.Parse;
// using (StringReader stringReader = new StringReader(objectXml))
// using (var xmlReader = XmlReader.Create(stringReader, settings))
{
retVal = serializer.Deserialize(reader);
return (T)retVal;
}
}
public static T Deserialize<T>(XDocument xdoc)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty, new XmlQualifiedName("xs", "http://www.w3.org/2001/XMLSchema") });
object retVal = null;
XmlSerializer serializer = new XmlSerializer(typeof(T));
var settings = new XmlReaderSettings();
settings.IgnoreComments = true;
settings.ConformanceLevel = ConformanceLevel.Document;
settings.DtdProcessing = DtdProcessing.Parse;
using (StringReader stringReader = new StringReader(xdoc.ToString()))
using (var xmlReader = XmlReader.Create(stringReader, settings))
{
retVal = serializer.Deserialize(xmlReader);
return (T)retVal;
}
}
public static T Deserialize<T>(string objectXml)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty, new XmlQualifiedName("xs", "http://www.w3.org/2001/XMLSchema") });
object retVal = null;
XmlSerializer serializer = new XmlSerializer(typeof(T));
var settings = new XmlReaderSettings();
settings.IgnoreComments = true;
settings.ConformanceLevel = ConformanceLevel.Document;
settings.DtdProcessing = DtdProcessing.Parse;
using (StringReader stringReader = new StringReader(objectXml))
using (var xmlReader = XmlReader.Create(stringReader, settings))
{
retVal = serializer.Deserialize(xmlReader);
return (T)retVal;
}
}
// public static T Deserialize<T>(string objectXml, string xmlNamespace)
// {
// var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty, new XmlQualifiedName("xs", xmlNamespace) });
// object retVal = null;
// XmlSerializer serializer = new XmlSerializer(typeof(T));
// var settings = new XmlReaderSettings();
// settings.IgnoreComments = true;
// settings.ConformanceLevel = ConformanceLevel.Document;
// settings.DtdProcessing = DtdProcessing.Parse;
// using (StringReader stringReader = new StringReader(objectXml))
// using (var xmlReader = XmlReader.Create(stringReader, settings))
// {
// retVal = serializer.Deserialize(xmlReader);
// return (T)retVal;
// }
// }
public static T Deserialize<T>(Stream xmlStream)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty, new XmlQualifiedName("xs", "http://www.w3.org/2001/XMLSchema") });
object retVal = null;
XmlSerializer serializer = new XmlSerializer(typeof(T));
var settings = new XmlReaderSettings();
settings.IgnoreComments = true;
settings.ConformanceLevel = ConformanceLevel.Document;
settings.DtdProcessing = DtdProcessing.Ignore;
using (var xmlReader = XmlReader.Create(xmlStream, settings))
{
retVal = serializer.Deserialize(xmlReader);
return (T)retVal;
}
}
}
}
public static class XmlUtil
{
public static string SerializeToString<T>(T value)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var serializer = new XmlSerializer(value.GetType());
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = false;
using (var stream = new StringWriter())
using (var writer = XmlWriter.Create(stream, settings))
{
// This adds our DocType
writer.WriteDocType("propertyList", null, "http://reaxml.realestate.com.au/propertyList.dtd", null);
serializer.Serialize(writer, value, emptyNamespaces);
return stream.ToString();
}
}
public static string SerializeToStringUTF8<T>(T value)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var serializer = new XmlSerializer(value.GetType());
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.Encoding = Encoding.UTF8;
settings.OmitXmlDeclaration = false;
using (var stream = new StringWriterWithEncoding(Encoding.UTF8))
using (var writer = XmlWriter.Create(stream, settings))
{
// This adds our DocType
writer.WriteDocType("propertyList", null, "http://reaxml.realestate.com.au/propertyList.dtd", null);
serializer.Serialize(writer, value, emptyNamespaces);
return stream.ToString();
}
}
I'm trying to get this:
<ATCWaypointEnd id="KLKP">
</ATCWaypointEnd>
But i get this:
<ATCWaypointEnd id="KLKP"></ATCWaypointEnd>
Here is my Code:
writer.WriteStartElement("ATCWaypointEnd");
writer.WriteStartAttribute("id");
writer.WriteString(ICAO);
writer.WriteFullEndElement();
I would recommend creating a class to represent your XML file and then use serialization. That way you can let the framework create the XML elements and you can easily specify whether it should contain line breaks or not (indentation).
You can also use an external tool to generate your POCO classes, for example: https://xmltocsharp.azurewebsites.net/
Using the piece of xml you provided:
// The class representing the XML file
[XmlRoot(ElementName="ATCWaypointEnd")]
public class ATCWaypointEnd
{
[XmlAttribute(AttributeName="id")]
public string Id { get; set; }
}
// The method that will return the object as a XML string
public static string GenerateXml(ATCWaypointEnd obj)
{
string xml;
using (var stream = new MemoryStream())
{
var serializer = new XmlSerializer(typeof(ATCWaypointEnd));
var writer = new XmlTextWriter(stream, encoding);
writer.Formatting = Formatting.Indented; // Here
serializer.Serialize(writer, obj);
xml = encoding.GetString(stream.ToArray());
}
return xml;
}
And then in your code you can use like this:
var obj = new ATCWaypointEnd();
obj.Id = "KLKP";
var xml = GenerateXml(obj);
You can do the following:
writer.WriteStartElement("ATCWaypointEnd");
writer.WriteAttributeString("id", ICAO);
writer.WriteString(System.Environment.NewLine);
writer.WriteFullEndElement();
See below for full code:
Add the following "using" statements:
using System.Xml;
using System.IO;
Option 1:
private void WriteXmlData(string ICAO, string filename)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = false;
settings.NewLineChars = Environment.NewLine;
string dirName = System.IO.Path.GetDirectoryName(filename);
if (!System.IO.Directory.Exists(dirName))
{
System.Diagnostics.Debug.WriteLine("Output folder doesn't exist. Creating.");
//create folder if it doesn't exist
System.IO.Directory.CreateDirectory(dirName);
}
using (XmlWriter writer = XmlWriter.Create(filename, settings))
{
writer.WriteStartDocument();
writer.WriteStartElement("ATCWaypointEnd");
writer.WriteAttributeString("id", ICAO);
writer.WriteString(System.Environment.NewLine);
writer.WriteFullEndElement();
writer.WriteEndDocument();
writer.Close();
writer.Dispose();
}
}
Usage:
WriteXmlData("KLKP", #"C:\Temp\test.xml");
Option 2:
private string WriteXmlData(string ICAO)
{
string xmlOutput = string.Empty;
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = false;
settings.NewLineChars = Environment.NewLine;
using (MemoryStream ms = new MemoryStream())
{
using (XmlWriter writer = XmlWriter.Create(ms, settings))
{
writer.WriteStartDocument();
writer.WriteStartElement("ATCWaypointEnd");
writer.WriteAttributeString("id", ICAO);
writer.WriteString(System.Environment.NewLine);
writer.WriteFullEndElement();
writer.WriteEndDocument();
writer.Close();
writer.Dispose();
}
//reset position
ms.Position = 0;
using (StreamReader sr = new StreamReader(ms))
{
//put XML into string
xmlOutput = sr.ReadToEnd();
//clean up
sr.Close();
sr.Dispose();
}
//clean up
ms.Close();
ms.Dispose();
}
return xmlOutput;
}
Usage:
string output = WriteXmlData("KLKP");
I have spent countless hours working on this issue, and have tried so many different things. Some background... I am working within an SSIS module using C# code to attempt to deserialize a SOAP XML stream. I have been able to deserialize XML streams before, but this one is significantly more complicated than the previous ones I have been involved with.
I have verified that the string I am using to populate my stream is correct for the results, and I am reaching the end of my rope.
Here is the method I am using to try to deserialize. You can see I have included several commented out sections to show some of the other methods I have used to try to make this work:
private Envelope GetWebServiceResultFromStream(StreamReader str)
{
bool b = true;
Envelope xmlResponse = null;
String xmlPayload = "";
//Deserialize our XML
try
{
//System.Runtime.Serialization.Formatters.Soap.SoapFormatter soapFormatter = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
//using (Stream savestream = str.BaseStream)
//{
// xmlResponse = (Envelope)soapFormatter.Deserialize(savestream);
//}
System.Xml.Serialization.XmlSerializer sr = new System.Xml.Serialization.XmlSerializer(typeof(Envelope));
using (Stream savestream = str.BaseStream)
{
StreamReader streamreader = new StreamReader(savestream, Encoding.UTF8);
xmlPayload = streamreader.ReadToEnd();
//xmlPayload = System.Security.SecurityElement.Escape(xmlPayload);
//xmlPayload = xmlPayload.Replace("&", "&");
//xmlPayload = xmlPayload.Replace("&", "&");
xmlPayload = xmlPayload.Replace("'", "'");
//xmlPayload = xmlPayload.Replace("soap:Envelope", "Envelope");
File.WriteAllText(#"myxml.xml",xmlPayload);
byte[] byteArray = Encoding.UTF8.GetBytes(xmlPayload);
MemoryStream secondstream = new MemoryStream(byteArray);
secondstream.Position = 0;
xmlResponse = sr.Deserialize(secondstream) as Envelope;
//xmlResponse = (Envelope)DeserializeFromXml<Envelope>(xmlPayload);
//XmlDocument doc = new XmlDocument();
//doc.Load(secondstream);
//XmlNodeReader reader = new XmlNodeReader(doc);
//using (reader)
//{
// xmlResponse = sr.Deserialize(reader) as Envelope;
//}
//System.Runtime.Serialization.Formatters.Soap.SoapFormatter soapFormatter = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
//xmlResponse = (Envelope)soapFormatter.Deserialize(secondstream);
}
//XmlDocument xmlSoapRequest = new XmlDocument();
//using (Stream savestream = str.BaseStream)
//{
// using (StreamReader readStream = new StreamReader(savestream, Encoding.UTF8))
// {
// xmlSoapRequest.Load(readStream);
// xmlPayload = xmlSoapRequest.SelectSingleNode("//Envelope/Body/GetRequisitionByDateResponse/").InnerText;
// }
//}
}
catch (Exception ex)
{
DumpException(ex);
this.ComponentMetaData.FireInformation(54, "", "Failed to deserialize: " + ex.Message + " Inner: " + ex.InnerException + " Source: " + ex.Source, "", 43, ref b);
}
return xmlResponse;
}
public static T DeserializeFromXml<T>(string xml)
{
T result;
var ser = new XmlSerializer(typeof(T));
using (var tr = new StringReader(xml))
{
result = (T)ser.Deserialize(tr);
}
return result;
}
I am using c# classes generated by feeding a response into the XML to C# converter (http://xmltocsharp.azurewebsites.net/). Unfortunately it appears the classes are too complex to put here (posts have a 30k character limit), so it has been pasted here:
http://txt.do/d91eo
I also pasted an example response:
http://txt.do/d91eb
I have consulted the wsdl and it appears that many DateTime fields are being read as strings through the converter. I am not sure if this is an issue, but I have tried to do my best to replace those data types and the error persisted.
Here is a screenshot of my error:
http://imgur.com/a/objJq
Other things I have tried:
Replacing invalid characters throughout the xml document (I found that it is doing this already, except in the case of some of the "'" characters).
Removed namespaces.
Marked all the classes as Serializable.
The Web Services object within SSIS (throws an error and doesn't let me enter any variables to send).
Regenerated the class list with a number of variants of the return result.
Found it
First add UTF8 to StreamReader : new StreamReader(FILENAME, Encoding.UTF8);
Here is your Root Class
[XmlRoot(ElementName = "Envelope", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public class Envelope
{
}
Here is you first line of XML
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
Compare Namespaces
The following code is running without exceptions. I can't include class because of size limitation. Note the namespace for Class Envelope I replaced "-" with "/". The class Envelope is constructed but all properties are null's because the namespace don't agree with the xml.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication50
{
class Program
{
static void Main(string[] args)
{
new Test();
}
}
public class Test
{
const string FILENAME = #"c:\temp\test2.xml";
public Test()
{
StreamReader reader = new StreamReader(FILENAME, Encoding.UTF8);
GetWebServiceResultFromStream(reader);
}
private Envelope GetWebServiceResultFromStream(StreamReader str)
{
bool b = true;
Envelope xmlResponse = null;
String xmlPayload = "";
//Deserialize our XML
try
{
//System.Runtime.Serialization.Formatters.Soap.SoapFormatter soapFormatter = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
//using (Stream savestream = str.BaseStream)
//{
// xmlResponse = (Envelope)soapFormatter.Deserialize(savestream);
//}
System.Xml.Serialization.XmlSerializer sr = new System.Xml.Serialization.XmlSerializer(typeof(Envelope));
using (Stream savestream = str.BaseStream)
{
StreamReader streamreader = new StreamReader(savestream, Encoding.UTF8);
xmlPayload = streamreader.ReadToEnd();
//xmlPayload = System.Security.SecurityElement.Escape(xmlPayload);
//xmlPayload = xmlPayload.Replace("&", "&");
//xmlPayload = xmlPayload.Replace("&", "&");
xmlPayload = xmlPayload.Replace("'", "'");
//xmlPayload = xmlPayload.Replace("soap:Envelope", "Envelope");
File.WriteAllText(#"myxml.xml",xmlPayload);
byte[] byteArray = Encoding.UTF8.GetBytes(xmlPayload);
MemoryStream secondstream = new MemoryStream(byteArray);
secondstream.Position = 0;
xmlResponse = sr.Deserialize(secondstream) as Envelope;
//xmlResponse = (Envelope)DeserializeFromXml<Envelope>(xmlPayload);
//XmlDocument doc = new XmlDocument();
//doc.Load(secondstream);
//XmlNodeReader reader = new XmlNodeReader(doc);
//using (reader)
//{
// xmlResponse = sr.Deserialize(reader) as Envelope;
//}
//System.Runtime.Serialization.Formatters.Soap.SoapFormatter soapFormatter = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
//xmlResponse = (Envelope)soapFormatter.Deserialize(secondstream);
}
//XmlDocument xmlSoapRequest = new XmlDocument();
//using (Stream savestream = str.BaseStream)
//{
// using (StreamReader readStream = new StreamReader(savestream, Encoding.UTF8))
// {
// xmlSoapRequest.Load(readStream);
// xmlPayload = xmlSoapRequest.SelectSingleNode("//Envelope/Body/GetRequisitionByDateResponse/").InnerText;
// }
//}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
//DumpException(ex);
//this.ComponentMetaData.FireInformation(54, "", "Failed to deserialize: " + ex.Message + " Inner: " + ex.InnerException + " Source: " + ex.Source, "", 43, ref b);
}
return xmlResponse;
}
public static T DeserializeFromXml<T>(string xml)
{
T result;
var ser = new XmlSerializer(typeof(T));
using (var tr = new StringReader(xml))
{
result = (T)ser.Deserialize(tr);
}
return result;
}
}
[XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
[XmlElement(ElementName = "Body", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public Body Body { get; set; }
[XmlAttribute(AttributeName = "soap", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Soap { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsd { get; set; }
}
}
I want to add
xsi:noNamespaceSchemaLocation="FullModeDataset.xsd"
and
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
as attibutes to my root node "ApplicationData" so the root node will look like this..
<ApplicationData
xsi:noNamespaceSchemaLocation="FullModeDataset.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
I am creating the xml from a string, outputing a string that is proper xml with this code..
var doc = new XmlDocument();
doc.LoadXml(myInputXmlString);
var ms = new MemoryStream();
var tx = XmlWriter.Create(ms,
new XmlWriterSettings
{
OmitXmlDeclaration = false,
ConformanceLevel = ConformanceLevel.Document,
Encoding = UTF8Encoding.UTF8
});
doc.Save(tx);
//I TRIED THE COMMENTED CODE BELOW BUT WITH NO SUCCESS
//XmlAttribute newAttr = doc.CreateAttribute("xsi:noNamespaceSchemaLocation");
//newAttr.Value = "FullModeDataset.xsd";
//XmlElement applicationNode = doc.DocumentElement["AppicationData"];
//applicationNode.Attributes.Append(newAttr);
//doc.Save(tx);
var xmlString = UTF8Encoding.UTF8.GetString(ms.ToArray());
how do I add these attributes to my xml string?
You need to create the attribute using the overload which takes the prefix and the namespace URL of the attribute you want to create, as shown below:
public class StackOverflow_14128649
{
public static void Test()
{
string myInputXmlString = #"<ApplicationData>
<something>else</something>
</ApplicationData>";
var doc = new XmlDocument();
doc.LoadXml(myInputXmlString);
XmlAttribute newAttr = doc.CreateAttribute(
"xsi",
"noNamespaceSchemaLocation",
"http://www.w3.org/2001/XMLSchema-instance");
newAttr.Value = "FullModeDataset.xsd";
doc.DocumentElement.Attributes.Append(newAttr);
var ms = new MemoryStream();
XmlWriterSettings ws = new XmlWriterSettings
{
OmitXmlDeclaration = false,
ConformanceLevel = ConformanceLevel.Document,
Encoding = UTF8Encoding.UTF8
};
var tx = XmlWriter.Create(ms, ws);
doc.Save(tx);
tx.Flush();
var xmlString = UTF8Encoding.UTF8.GetString(ms.ToArray());
Console.WriteLine(xmlString);
}
}
In order to return useful information in SoapException.Detail for an asmx web service, I took an idea from WCF and created a fault class to contain said useful information. That fault object is then serialised to the required XmlNode of a thrown SoapException.
I'm wondering whether I have the best code to create the XmlDocument - here is my take on it:
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);
}
Is there a better way of doing this?
UPDATE: I actually ended up doing the following, because unless you wrap the XML in a <detail> xml element, you get a SoapHeaderException at the client end:
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: Given John Saunders excellent answer, I've now started using the following:
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();
}
EDIT: Creates output inside of detail element
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;
}