When do we use XMLSerialization? - c#

I was searching on examples as how to store data in isolated storage. In an example XmlSerializer was used. I have given the code below. Please explain the function and need for Xmlserializer.
XmlSerializer ser = new XmlSerializer(typeof(TravelReportInfo));
ser.Serialize(fs, travelReportInfo);

XmlSerialization is the process of taking an object and representing it as xml. Xml is one of the ideal formats for this since it can describe arbitrary object hierarchies.
One common use case is transfering objects over the web. If you serialize your object to xml you can include it in http requests and responses and deserialize it back to its original object on the other side. All information to reconstruct the object is found in the xml
Bellow you can see an example of a class serialized to xml
public class OrderForm
{
public DateTime OrderDate;
}
<OrderForm>
<OrderDate>12/12/01</OrderDate>
</OrderForm>

Related

How to ensure that the class library represents the Json Schema perfectly

I have a JSON Schema, and a class library.
I am able to serialize this class, then convert back successfully to object.
To test it, I create a random object, serialize it.
Then convert to object and check its validity.
And deserialize it just to be sure about the values.
The code below works perfectly - but
I want to be absolutely sure that the class library represents the Json Schema.
Is there a way to achieve this? I found some online tools tries to create the class library from given schema, but none of them were so useful.
// Create random object.
MyObject myObject = new MyObject().CreateRandomMyObject();
// Serialize it.
string JSONObjectText = JsonConvert.SerializeObject(myObject);
// Check if schema is valid.
JSchema schema = JSchema.Parse(txtSchema.Value);
// Check if the serialized object is valid for schema.
JObject jsonObject = JObject.Parse(JSONObjectText);
IList<string> errorMessages;
bool valid = jsonObject.IsValid(schema, out errorMessages);
// Check if the serialized object can be deserialized.
MyObject myObjectReDeserialized = (MyObject)JsonConvert.DeserializeObject(JSONObjectText, typeof(MyObject), new JsonSerializerSettings() { MissingMemberHandling = MissingMemberHandling.Error });
A way to do test-oriented assertion of your mapping is to use FsCheck to generate plenty of random objects and then assert what you want to hold from them: in this case, that
their serialization is valid given the schema,
they can be deserialized back to the same object. (You should make sure you are using structural equality there.)
To be precise, such approach only checks that everything described by your objects is representable by the schema. You might want to do the other way also -- that every JSON that conforms to the schema is representable by your objects. Again, you can generate many possible JSONs conforming to the schema and check that
they can be deserialized to your objects,
reserialization of those objects gives you the same JSON you started with.
Beware though, this might not be practical: FsCheck probably don't have some nice, first-class support for JSON schema based generation out-of-the-box.
If the schema you have is going to change in the future, it would be really great to have a way to generate corresponding objects to have strong types even at the boundary of your application. Have you tried Swagger Codegen? Swagger describes it's endpoints using subset of JSON Schema. The corresponding tooling might help you.

Dummy Objects Good or Bad

I am working on a project that communicates a lot of data with a server. This data is in a json format. We end up creating a lot of dummy objects to parse the json data. This leads to having a lot of classes that just contain class members. Is there a better way of doing things?
thanks
Assuming that you are using NewtonSoft's JSON parser or something similar, you have a couple of choices here. The usual use case here is to deserialize to a named type, thus:
var parsedMessage = JsonConvert.DeserializeObject<Message>(content.AsString());
If you have many types for each differnet JSON message type you wish to receive and wish to avoid to, you can do the following:
var parsedMessage = JsonConvert.DeserializeObject<dynamic>(content.AsString());
This will give you a dynamic object that you can inspect and should also work given other Json libraries. Alternatively, NetwtonSoft also provides the following method:
public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject);
This will allow you to deserialize to an anonymously typed object rather than a dynamic object.

Integration of Serialization and Deserialization in Builder Design Pattern using C#

I am implementing the Builder Pattern in order to generate a set of objects. These objects then have to be serialized to XML and deserialized from XML.
I know how to perform the serialization and deserialization however I am unsure how to integrate it into the design pattern.
For example suppose my code uses the builder to create products foo and bar. My first thought is to put a serialize function on each one because each product knows what to serialize.
My next thought was to put the deserialization in the Director or the ConcreteBuilder.
What I don't like about this is that the serialization and deserialization functions will be in different places - one in the file for the declaration of the foo and bar objects and the other in the files for something else. I am worried that they might end up becoming out of sync with each other as I work on the product classes.
My final thought was for the Director or ConcreteBuilder to perform the serialization and deserialization. What I don't like about that is the products then have to know which builder was used or know who the Director is.
To clarify - there are two situations where a product can be created:
User clicks on a button in the user interface
User loads a XML project
Can you not simply have a static serialize/deserialize class and create a generic method that can take any type of object? Isn't the pattern simply for building the objects? You can then serialize as you wish?
Something like:
public static string Serialize<T>(T data)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
StringWriter sw = new StringWriter();
xmlSerializer.Serialize(sw, data);
return sw.ToString();
}
My current solution is to have the Product perform the serialization and the ConcreteBuilder perform the deserialization, then put both the Product and it's ConcreteBuilder declarations into the same source file.
Although the task is spread across two classes it is at least kept together in one file.
Any better solutions are appreciated.

Parsing an XML file -options?

I'm developing a system to pick up XML attachments from emails, via Exchange Web Services, and enter them into a DB, via a custom DAL object that I've created.
I've manage to extract the XML attachment and have it ready as a stream... they question is how to parse this stream and populate a DAL object.
I can create an XMLTextReader and iterate through each element. I don't see any problems with this other than that I suspect there is a much slicker way. The reader seems to treat the opening tag, the content of the tag and the closing tag as different elements (using reader.NodeType). I expected myValue to be considered one element rather than three. Like I said, I can get round this problem, but I'm sure there must be a better way.
I came across the idea of using an XML Serializer (completely new to me) but a quick look suggested that these can't handle ArrayLists and List (I'm using List).
Again, I'm new to LINQ, but LINQ-to-XML has also been mentioned, but examples I've seen seem rather complex - though that my simply be my lack of familiarity.
Basically, I don't want a cludged system, but I don't want to use any complicated technique with a learning curve, just because it's 'cool'.
What is the simplest and most effective way of translating this XML/Stream in to my DAL objects?
XML Sample:
<?xml version="1.0" encoding="UTF-8"?>
<enquiry>
<enquiryno>100001</enquiryno>
<companyname>myco</companyname>
<typeofbusiness>dunno</typeofbusiness>
<companyregno>ABC123</companyregno>
<postcode>12345</postcode>
<contactemail>me#example.com</contactemail>
<firstname>My</firstname>
<lastname>Name</lastname>
<vehicles>
<vehicle>
<vehiclereg>54321</vehiclereg>
<vehicletype>Car</vehicletype>
<vehiclemake>Ford</vehiclemake>
<cabtype>n/a</cabtype>
<powerbhp>130</powerbhp>
<registrationdate>01/01/2003</registrationdate>
</vehicle>
</vehicles>
</enquiry>
Update 1:
I'm trying to deserialize, based on Graham's example. I think I've set up the DAL for serialization, including specifying [XmlElement("whatever")] for each property. And I've tried to deserialize using the following:
SalesEnquiry enquiry = null;
XmlSerializer serializer = new XmlSerializer(typeof(SalesEnquiry));
enquiry = (SalesEnquiry)serializer.Deserialize(stream);
However, I get an exception:'There is an error in XML document (2, 2)'. The innerexception states {"<enquiry xmlns=''> was not expected."}
Conclusion (updated):
My previous problem was the fact that the element in the XML file (Enquiry) != the name of the class (SalesEnquiry). Rather than an [XmlElement] attribute for the class, we need an [XmlRoot] attribute instead. For completeness, if you want a property in your class to be ignored during serialization, you use the [XmlIgnore] attribute.
I've successfully serialized my object, and have now successfully taken the incoming XML and de-serialized it into a SalesEnquiry object.
This approach is far easier than manually parsing the XML. OK, there has been a steep learning curve, but it was worth it.
Thanks!
If your XML uses a schema (i.e. you're always going to know what elements appear, and where they appear in the tree), you could use XmlSerializer to create your objects. You'd just need some attributes on your classes to tell the serializer what XML elements or attributes they correspond to. Then you just load up your XML, create a new XmlSerializer with the type of the .NET object you want to create, and call the Deserialize method.
For example, you have a class like this:
[Serializable]
public class Person
{
[XmlElement("PersonName")]
public string Name { get; set; }
[XmlElement("PersonAge")]
public int Age { get; set; }
[XmlArrayItem("Child")]
public List<string> Children { get; set; }
}
And input XML like this (saved in a file for this example):
<?xml version="1.0"?>
<Person>
<PersonName>Bob</PersonName>
<PersonAge>35</PersonAge>
<Children>
<Child>Chris</Child>
<Child>Alice</Child>
</Children>
</Person>
Then you create a Person instance like this:
Person person = null;
XmlSerializer serializer = new XmlSerializer(typeof(Person));
using (FileStream fs = new FileStream(GetFileName(), FileMode.Open))
{
person = (Person)serializer.Deserialize(fs);
}
Update:
Based on your last update, I would guess that either you need to specify an XmlRoot attribute on the class that's acting as your root element (i.e. SalesEnquiry), or the XmlSerializer might be a bit confused that you're referencing an empty namespace in your XML (xmlns='' doesn't seem right).
XmlSerializer does support arrays & lists... as long as the contained type is serializable.
I have found Xsd2Code very helpful for this kind of thing: http://xsd2code.codeplex.com/
Basically, all you need to do is write an xsd file (an XML schema file) and specify a few command line switches. Xsd2Code will automatically generate a C# class file that contains all the classes and properties plus everything needed to handle the serialization. It's not a perfect solution as it doesn't support all aspects of XSD, but if your XML files are relatively simple collections of elements and attributes, it should be a nice short-cut for you.
There's another similar project on Codeplex called Linq to XSD (http://linqtoxsd.codeplex.com/), which was designed to enforce the entire XSD specification, but last time I checked, it was no longer being supported and not really ready for prime time. Thought it was worth a mention, though.

Serialize C# class directly to SQL server?

can anyone suggest the best way to serialize data (a class actually) to a DB?
I am using SQL server 2008 but i presume i need to serialize the class to a string / or other data type before storing in the database?
I presume that this field needs to be text or binary??
Does SQL server 2008 (or .net 3.5) support serializing directly tothe database ??
Any help really appreciated
You can xml serialize the class into an xml field. We use this all the time for exception logging in an ETL.
Using the XmlSerializer you may want a helper method somewhere which serializes the class to a string...
public static string SerializeToXml<T>(T value)
{
StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(writer, value);
return writer.ToString();
}
Then just put the string into the db like any other.
The best way to store data in a database is in columns (per property), so that it is queryable and indexable. ORM tools will help with this.
However, it is also possible to serialize a class as a CLOB/BLOB (varchar(max)/varbinary(max) etc).
It this is what you want, avoid anything implementation-specific or version-intolerant; so in particular, don't use BinaryFormatter. Anything contract-based should work; XmlSerializer, DataContractSerializer, etc. Or for fast binary, protobuf-net might be worth a look.
But I stress; columns would be better.
Without generics (better sollution)
public static string SerializeToXml(object value)
{
StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
XmlSerializer serializer = new XmlSerializer(value.GetType());
serializer.Serialize(writer, value);
return writer.ToString();
}
I've serialized objects as XML and thrown those into the database just fine. Since we knew the max amount of text we used the varchar(max) datatype instead of getting into TEXT or Binary formats.
This was a OLTP web application and one thing we found was that using a column with an xml datatype invoked some significant cpu usage as the xml was validated on every insert. In our case the xml was never queried for anything so not having the xml query capabilities worked out ok for us.
There are couple of options:
Runtime serialization, serializable objects are marked with the
Serializable attribute, in which case the IFormatter class does all the work of
serialization. A serializable object can ISerializable, but then you will
need to implement the GetObjectData( ) method. The problem with runtime serialization is that program reading the xml data needs to have
the knowledge of the CLR types.
Xml serialization: Unline runtime serialization, you will get good interoperability in this case.
The XmlSerializer type contains the methods Serialize( ) and Deserialize( ), thus
any object can be serialized to XML and saved into the database and when you retreive it back, you
can deserialize it easily.
To read data from the database, you can use the SqlCommand class
method that executes SQL queries, namely ExecuteXmlReader( ).
ExecuteXmlReader( ) returns an instance of XmlReader and that will read your xml data.
Check out Linq-to-SQL (questions on SO, resource on MSDN) or other O-R Mapping options.

Categories