Capture serialised XML when deserialising - c#

.net, C#
Is it easily possible (by use of attributes etc) to automatically save the entire XML string (as a string field) that was created when an object was serialised when that object is deserialised?
I ask because I'm receiving an XML stub from a web service, and that stub contains a digital signature that I can use to verify the XML. I can deserialise the XML into a useful object that can be passed down into my application layer for verification, but I need the XML too. Ideally my new object would have an OriginalXML property or something. I could verify the XML at a higher level but it's not so convenient for me.
Cheers,
Chris.

You can load the XML file into a string, no problem. But the OriginalXML property would have to be marked with the [NonSerialized] attribute, because you don't want to store that string when you serialize. You'll have to deserialize, reload as an XmlDocument, and store the resulting string to that property.
XmlDocument xmlDoc = new XmlDocument();
try {
xmlDoc.Load(serializedFile);
}
catch (XmlException exc) {
// Handle the error
}
StringWriter stringWriter = new StringWriter();
XmlTextWriter xmlWriter= new XmlTextWriter(stringWriter);
xmlDoc.WriteTo(xmlWriter);
myObject.OriginalXML = xmlWriter.ToString();
HTH,
James

How about
[DataContract]
class FooBar
{
//this property doesn't have the DataMember attribure
//and thus won't be serialized
public string OriginalXml { get; set; }
[DataMember] private int _foo;
[DataMember] private string _bar;
static public FooBar Deserialize(XmlReader reader)
{
var fooBar =
(FooBar)new DataContractSerializer(typeof(FooBar)).ReadObject(reader);
fooBar.OriginalXml = reader.ToString();
return fooBar;
}
}

Related

Getting information from my XML

I'm quite new to XML serialization/deserialization and I'm wondering how I should apply tags (XmlElement, XmlAttribute etc) to the following objects which I'm writing to XML files, to make it most optimal for me to later use LINQ or similar to get out the data I want. Let me give an example:
[XmlRoot("Root")]
public class RootObject
{
public Services Services { get; set; }
}
public class Services
{
public Service TileMapService { get; set; }
}
public class Service
{
public string Title { get; set; }
public string href { get; set; }
}
Here I've defined some properties which I'm going to write to XML with some values I'm gonna add later. At this point, I've hardcoded in the values in this method:
public static void RootCapabilities()
{
RootObject ro = new RootObject()
{
Services = new Services()
{
TileMapService = new Service()
{
Title = "Title",
href = "http://something"
}
}
};
Which gets me this XML output:
<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Services>
<TileMapService>
<Title>Title</Title>
<href>http://something</href>
</TileMapService>
</Services>
</Root>
My question is if this is a valid way of doing it or if I have to use the 'XmlElement' and 'XmlAttribute' tags to later deserialize this XML file and get the information out of it, that I want (for example 'title').
I haven't been sure how to write this question, so please let me know if it's too vague.
I would not use XML serialization if I were you. Any changes to your schema/object structure and you immediately lose backwards compatibility due to how XML serialization works as a technology.
Rather separate out the XML serialization from the actual class structure - this way you can make changes to the XML/object schema and write proper migrating functions to handle any changes you make in the future.
Rather use the LINQ-to-XML classes to construct your XML document and save it as they are the easiest way in .NET to convert object structures to XML in a decoupled manner.
if the output is what you expect I think that you shouldn't change anything.
You should use Decorators like XmlAttribute or XmlIgnore when you want change the default behavior (e.g don't include a field, include one field as an attribute...)
Their role is obtain full control of the serialization and avoid unexpected behaviors
If you don't want to worry about the nitty-gritty of the serialization, XmlSerializer has always treated me well.
public static void SerializeObject(T obj, string file)
{
XmlSerializer s = new XmlSerializer(typeof(T));
TextWriter w = new StreamWriter(file);
s.Serialize(w, obj);
w.Close();
}
public static T DeserializeObject(string file)
{
XmlSerializer s = new XmlSerializer(typeof(T));
using (StreamReader r = new StreamReader(file))
{
return (T)s.Deserialize(r);
}
}
This should really only be used with references types though (objects, not primitive types or structs). Deserialize can return null and casting that to a value type will bring nothing but heartache.

How to prevent object to be serialize in XML

IDE: VS, C# .net 4.0, winforms
With the help of XMLSerializer I am able to generate XML of C# object, but I want to remove specific objects.
Is there any way to prevent specific objects to prevent in XML..?
using (MemoryStream xmlStream = new MemoryStream())
{
/*
XmlSerializer.Serialize Method (XmlWriter, Object)
Serializes the specified Object and writes the XML document to a file using the specified xmlwriter
Parameters
xmlWriter-
Type: System.Xml.XmlWriter
The XmlWriter used to write the XML document.
Type: System.Object
The Object to serialize.
*/
xmlSerializer.Serialize(xmlStream, YourClassObject);
xmlStream.Position = 0;
//Loads the XML document from the specified string.
xmlDoc.Load(xmlStream);
string fileName = YourClassObject.GetType().Name;
xmlDoc.Save("C:\\Users\\Yogesh\\Desktop\\Yardz_XMLS\\" + fileName + ".xml");
return xmlDoc.InnerXml;
Is there any way to prevent some properties to be serialize..?
Put XmlIgnore attribute on properties that you don't what to be serialized:
public class YourClass
{
public string Serailized { get; set; }
[XmlIgnore]
public string NotSerialized { get; set; }
}
See "Controlling XML Serialization Using Attributes" for more information.

Serialize/Deserialize different property names?

I have an old system which in a request info call returns xml with names that look like:
postalCodeField, firstNameField...
That same system then has a modify call which takes xml that looks like:
PostalCode, fistName, lastName....
Is there a way to build an object that would deserialize the request, yet serialize the xml output with different names?
Specifically:
public class RequestInfo
{
public string firstNameField{get;set;}
public string lastNameField{get;set;}
}
public class ModifyInfo
{
public string firstName{get;set;}
public string lastName{get;set;}
public ModifyInfo(){}
public ModifyInfo(RequestInfo ri)
{
firstName = ri.firstNameField
.....
}
}
Is there a way through say attributes to make these into the same object?
EDIT
Is there a way to have a single object that would accept one tag name on deserialize, then output a different name on serialize?
< myTagField /> (deserialize to) myObj.MyTag (serialize to) < MyTag />
It's important to note which actual serializer you're using. Every different serializer works differently.
I assume you're using the System.Xml.Serialization.XmlSerializer. If that is the case, then you want to use the attributes in the System.Xml.Serialization namespace such as XmlElementAttribute like so:
public class Person
{
[System.Xml.Serialization.XmlElement(ElementName = "firstNameField")]
public string FirstName { get; set; }
}
This assumes the field is an XML element. If it's an attribute, use the XmlAttribute attribute.
Check Attributes That Control XML Serialization on MSDN. You will need XmlElement for properties and, possibly, XmlRoot for root class.
If you need to override property names only during deserialization, than you can define attributes dynamically, using XmlAttributeOverrides:
public XmlSerializer CreateOverrider()
{
XmlElementAttribute xElement = new XmlElementAttribute();
xElement.ElementName = "firstName";
XmlAttributes xElements = new XmlAttributes();
xElements.XmlElements.Add(xElement);
XmlAttributeOverrides xOver = new XmlAttributeOverrides();
xOver.Add(typeof(RequestInfo), "firstNameField", xElements);
XmlSerializer xSer = new XmlSerializer(typeof(RequestInfo), xOver);
return xSer;
}

System.Reflection.RuntimeParameterInfo is inaccessible due to its protection level

I get the following error when trying to serialize a generic list
"System.Reflection.RuntimeParameterInfo is inaccessible due to its protection level. Only public types can be processed"
here is my code below
XmlSerializer serializer = new XmlSerializer(typeof(List<System.Reflection.ParameterInfo>));
XDocument document = new XDocument();
using (XmlWriter xmlWriter = document.CreateWriter())
{
serializer.Serialize(xmlWriter, parameterList);
}
return document.Root.ToString();
Not all types are serializable. With a serializer such as XmlSerializer, your best approach is to write a DTO that has the parts that you are interested in, for example:
public class Parameter {
public string Name {get;set;}
public string TypeName {get;set;}
public bool ByRef {get;set;}
}
then populate that from the ParameterInfo, and serialize that. Note that some things are problematic here, for example it would be very inconvenient to serialize a DefaultValue, unless you serialize it as a string and parse it back at the receiver.

How would I deserialize some class from XML (file), and vice versa?

I have the following class and data members (plus irrelevant methods) I am new to XML and .NET (that excuse is getting old though) and have spent a couple of days reading the MSDN entries (and whatever google turned up) for first XMLReader, then XMLDocument and now XDocument, XElement and XNode but am no closer to a concrete solution to serializing my class (perhaps I need to study serialization in .NET in more depth). To get me started I have some data in an XML file that I want to read (although it prolly is in the wrong format) in to initialize a class to initialize my application. The configuration class is as follows:
class IWantToFile
{
class DirsAndFiles
{
public List<string> Suffixes;
public string Dir;
}
enum OPOptsEnum
{
op1Description, op2Description, op3Description, op4Description,
op5Description, op6Description, op7Description, op8Description,
};
List<DirsAndFiles> ProjectDirs;
bool[] OPOpts = new bool[(int)OPOptsEnum.op8Description + 1];
bool otherOpt;
}
Observing the one to one and one to many relationships therein (eg List<DirsAndFiles> ProjectDirs) can someone please give concise methods to read and write this data to a file? It would greatly assist my development in these fields.
I've got as far as:
if (File.Exists(SPECFILENAME)) {
XDocument xdoc = XDocument.Load(SPECFILENAME);
//Ummm.....
}
but then my lack of .NET XML and Linq exeperience fail me.
I think you might want to use the XmlSerializer, which 'Serializes and deserializes objects into and from XML documents'?
See How to serialize an object to XML by using Visual C# for sample code.
[Serializable]
public class MyObject
{
public string SerializeMe { get; set; }
[XmlIgnore]
public string DONTSerializeMe { get; set; }
}
Helper....
public static class SerializerHelper<T>
{
public static string Serialize(T myobject)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
StringWriter stringWriter = new StringWriter();
xmlSerializer.Serialize(stringWriter, myobject);
string xml = stringWriter.ToString();
return xml;
}
public static T Deserialize(string xml)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
StringReader stringReader = new StringReader(xml);
return (T)xmlSerializer.Deserialize(stringReader);
}
}
Usage
MyObject myObject = new MyObject();
string xml = SerializerHelper<MyObject>.Serialize(myObject);
MyObject DeserializedObject = SerializerHelper<MyObject>.Deserialize(xml);

Categories