Universal conversion of types - c#

Assuming I have a table Entities with the columns Value and Type as varchar(strings) in a database, how would I go around to loading these values in C# and converting to the type specified in the table? I was intending to save the getType result for the Type value.

Save the value.GetType().AssemblyQualifiedName in the Type column and then use Type.GetType(asmQualfName) to get the type back when loading from the db. After that you can just use Activator.CreateInstance to get an object of the correct type.

How do you read from your database?
Are you using ADO.NET, or are you using any kind of OR Mapper such as EF or NHibernate? In the case of OR Mapping you could build a strongly typed object which could define the types... the OR mapper itself is responsible for the casting.

You can do this by Activator.CreateInstance Method for sample code (which is very similar to ur case) see MSDN Sample linked above.

When you're not using any OR mapper, I would prefer to build a simple class and serialize the instance of that type into xml and store in in a xml column within the databse.
using System.Xml.Serialization;
public class MySettings
{
public String Setting1 { get; set; }
public int Setting2 { get; set; }
public String ToXml()
{
string settingsXml;
var xmlSerializer = new XmlSerializer(typeof(MySettings));
using (var stream = new MemoryStream())
{
xmlSerializer.Serialize(stream, this);
stream.Position = 0;
using(var reader = new StreamReader(stream))
{
settingsXml = reader.ReadToEnd();
}
}
return settingsXml;
}
public static MySettings FromXml(string xml)
{
MySettings settings = null;
using(MemoryStream stream = new MemoryStream(System.Text.Encoding.Default.GetBytes(xml)))
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof (MySettings));
settings = (MySettings) xmlSerializer.Deserialize(stream);
}
return settings;
}
}

Related

XmlSerializer not deserializing XML to IEnumerable

While referencing one of the Stack Overflow posts, XmlSerializer won't serialize IEnumerable, I have the following code that would serialize to XML correctly but when deserialized back, the IEnumerable comes back empty.
using System.Xml.Linq;
using System.Xml.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
public class Hello{
public static void Main(){
// <!--- Serializing part -->
Glossary glossary1 = new Glossary();
glossary1.Term = "Test1";
glossary1.Definition = "Test1";
Glossary glossary2 = new Glossary();
glossary2.Term = "Test2";
glossary2.Definition = "Test2";
List<Glossary> glossaryList = new List<Glossary>();
glossaryList.Add(glossary1);
glossaryList.Add(glossary2);
GlossaryCollection glossary = new GlossaryCollection(glossaryList);
XDocument doc = new XDocument();
XmlSerializer xmlSerializer = new XmlSerializer(typeof(GlossaryCollection));
using (var writer = doc.CreateWriter()) {
xmlSerializer.Serialize(writer, glossary);
}
doc.Save("test.xml");
XDocument doc2 = XDocument.Load("test.xml");
Console.WriteLine(glossary.glossaryList.Count());
Console.WriteLine(doc2.ToString());
//So far looks good - serializing works fine!
// </!--- Serializing part -->
// <!--- De-Serializing part -->
GlossaryCollection temp2;
xmlSerializer = new XmlSerializer(typeof(GlossaryCollection));
using (var reader = doc2.Root.CreateReader()) {
var temp = xmlSerializer.Deserialize(reader);
temp2 = (GlossaryCollection) temp;
}
Console.WriteLine(temp2.glossaryList.Count()); // Results in 0, should be 2... :(
// </!--- De-Serializing part -->
}
[XmlRoot]
public class GlossaryCollection {
[XmlIgnore]
public IEnumerable<Glossary> glossaryList;
[XmlElement]
public List<Glossary> GlossarySurrogate { get { return glossaryList.ToList(); } set { glossaryList = value; } } // https://stackoverflow.com/questions/9102234/xmlserializer-wont-serialize-ienumerable
public GlossaryCollection() {
glossaryList = new List<Glossary>();
}
public GlossaryCollection(IEnumerable<Glossary> glossaryList) {
this.glossaryList = glossaryList;
}
}
[XmlType("Glossary")]
public class Glossary
{
public string Id { get; set; }
public string Term { get; set; }
public string Definition { get; set; }
}
}
Update: Based on Iridium's answer, it does not seem possible to use IEnumerable with XmlSerializer since it was returning a new list everytime, so went with the approach of converting to a List. However if there is a solution (even if hacky) with keeping glossaryList an IEnumerable, do let me know - even if simply for pure curiosity.
When your XML-serialized type has a property of type List<T>, XmlSerializer will get the value of the property, then call .Add(...) to add the deserialized elements (i.e. it does not set the property).
Since the getter for the GlossarySurrogate property returns a new list every time you get it, the changes the XML serializer makes to the result are lost.
If you want this to work correctly, you're going to need to convert your glossaryList field to a List<Glossary> and return it directly from the GlossarySurrogate getter, without calling .ToList() on it.

Error while serializing a class to XML

I am serializing Linq object to using XmlSerializer but I am getting
"There was an error reflecting type
'System.Collections.Generic.List`1"
I have extended the Linq object with Serilizable attributes, something that m I doing incorrect here?
[Serializable]
public partial class Customer
{
}
[Serializable]
public partial class Comment
{
}
[Serializable]
public class CustomerArchive
{
public Customer MyCustomer{ get; set; }
public Comment MyComment { get; set; }
}
internal static void Serialize(IEnumerable<CustomerArchive> archive, string fileName)
{
var serializer = new XmlSerializer(typeof(List<CustomerArchive>)); // Error
using (var stream = File.Create(fileName))
{
using (var sw = new StreamWriter(stream))
using (var writer = new XmlTextWriter(sw)
{
Indentation = 5,
Formatting = Formatting.Indented
})
serializer.Serialize(writer, new List<CustomerArchive>(archive));
}
}
I think you have some properties inside MyCustomer class that cannot be serialized by the XML Serializer. Like a generic Dictionary<> for example.
Put [XmlIgnore] attribute on those properties and try again. If after that your code works you will simply need to make some surrogate properties that would serialize to XML and back without any issues.

Can I serialize Xml for an MVC Web API without an object type?

So I'm writing my first mvc page, and I'm trying to write a series of routes to allow a reporting system to create simple reports. The xml is small, here is an example:
<xml><root><item><value>23</value></item></root>
I tried this:
using (StringWriter xmlStringWriter = new StringWriter())
{
using (XmlWriter xmlWriter = XmlWriter.Create(xmlStringWriter))
{
XmlWriter.WriteStartElement("root")
...
}
return xmlStringWriter.ToString();
}
but this obviously returns a string and is not interpreted as xml by the browser. I also know* that if you return an object that is serializable then the browser knows to interpret that as xml or json. So I tried defining a set of objects to hold each other in the way the xml is nested:
[Serializable]
public class XmlReportRoot
{
[System.Xml.Serialization.XmlAttribute("root")]
public List<XmlReportItem> item { get; set; }
}
[Serializable]
public class XmlReportItem
{
[System.Xml.Serialization.XmlAttribute("item")]
public XmlReportValue value { get; set; }
}
[Serializable]
public class XmlReportValue
{
[System.Xml.Serialization.XmlAttribute("value")]
public string count { get; set; }
}
and:
XmlReportRoot xmlRoot = new XmlReportRoot();
XmlReportItem xmlItem = new XmlReportItem();
List<XmlReportItem> itemList = new List<XmlReportItem>();
itemList.Add(xmlItem);
XmlReportValue xmlValue = new XmlReportValue();
xmlValue.count = newCustomers.ToString();
xmlItem.value = xmlValue;
xmlRoot.item = itemList;
XmlSerializer xmlSer = new XmlSerializer(typeof(XmlReportRoot));
xmlSer.Serialize(xmlRoot); //this line doesn't work
but this just feels wrong, and I couldn't quite get the serialization to work without worrying about a file stream, which I would rather do.
So I guess I was trying to find a way to do something like XmlWriter but be able to serialize that without an object type and return that, instead of having to worry about custom serializable objects types.
Use XmlWriter.Create(Response.OutputStream) and Response.ContentType = "application/xml"

convert javascript object into c# object

I am working on client side programming and I want to convert a javascript object into c# object so that I can save it in database.
Is there any method to achieve this ?
Thanks
javascript:
var obj = {id:0,userName:'Bill'};
c#,
define class:
public class myClass
{
public int id;
public string userName;
}
then transport obj to server (for example using AJAX request), and deserialize, when you need work with object
myClass obj = (new JavascriptSerializer()).Deserialize<myClass>(objJson);
But you can do without deserialization and store objJson string to database
First you will need to pass the JSON object to the server side possibly using a web service in code behind and then you could try this awesome library:
JSON.net
The biggest hurdle you're going to have to overcome here regardless of what serialization/deserialzation technique you decide to go with is how you're going to pass the JSON string from the client side to your code behind where you can use it. For this I recommend using jQuery's AJAX capabilities. This article proved invaluable to me when I was learning how to pass information from the client
For this solution to work you need the type represented by T to be of a type that is decorated with DataContract and DataMember attributes. The DataContractJsonSErializer is WAY better than JavascriptSerializer. This is from some code I wrote for a C# REST client. It does show how to serialize and deserialize generically though. Example object included
[DataContract]
public SampleObject
{
[DataMember("MyProperty")]
public string MyProperty {get;set;}
}
private static byte[] SerializeRequest<T>(string contentType, T request)
{
using (MemoryStream requestObjectStream = new MemoryStream())
{
if (contentType == "applicaton/json")
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
serializer.WriteObject(requestObjectStream, request);
}
else if (contentType == "application/xml")
{
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(requestObjectStream, request);
}
else
{
throw new Exception("invalid contentType");
}
requestObjectStream.Position = 0;
return requestObjectStream.ToArray();
}
}
private static T DeserializeResponse<T>(string acceptHeader, string responseString)
{
if (acceptHeader == "applicaton/json")
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
MemoryStream responseObjectStream = new MemoryStream(Encoding.UTF8.GetBytes(responseString));
return (T)serializer.ReadObject(responseObjectStream);
}
else if (acceptHeader == "application/xml")
{
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
MemoryStream responseObjectStream = new MemoryStream(Encoding.UTF8.GetBytes(responseString));
return (T)serializer.ReadObject(responseObjectStream);
}
return default(T);
}

Error converting JSON to .Net object in asp.net

I am unable to convert JSON string to .net object in asp.net. I am sending JSON string from client to server using hidden field (by keeping the JSON object.Tostring() in hidden field and reading the hidden field value in code behind file)
Json string/ Object:
[[{"OfferId":"1","OrderValue":"11","HostingTypeID":"3"},
{"OfferId":"1","OrderValue":"11","HostingTypeID":"3"},
{"OfferId":"1","OrderValue":"11","HostingTypeID":"3"},
{"OfferId":"1","OrderValue":"2","HostingTypeID":"3"},
{"OfferId":"1","OrderValue":"2","HostingTypeID":"3"},
{"OfferId":"1","OrderValue":"67","HostingTypeID":"3"},
{"OfferId":"1","OrderValue":"67","HostingTypeID":"3"}],
[{"OfferId":"1","OrderValue":"99","HostingTypeID":"6"}],
[{"OfferId":"1","OrderValue":"10","HostingTypeID":"8"}]]
.Net Object
public class JsonFeaturedOffer
{
public string OfferId { get; set; }
public string OrderValue { get; set; }
public string HostingTypeID { get; set; }
}
Converstion code in code behind file
byte[] byteArray = Encoding.ASCII.GetBytes(HdnJsonData.Value);
MemoryStream stream = new MemoryStream(byteArray);
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(JsonFeaturedOffer));
object result= serializer.ReadObject(stream);
JsonFeaturedOffer jsonObj = result as JsonFeaturedOffer;
While converting i am getting following error:
Expecting element 'root' from namespace ''.. Encountered 'None' with name '', namespace ''.
Unfortunately, none of the proposed solutions solve the real source of the problem. This exception means that your deserializer tries to read from the end of a stream.
The solution is to rewind the stream to the beginning, ie. set the stream.Position = 0; before deserialization.
Also, as the comments mention, if you used a StreamWriter you need to flush it before using the stream.
Instead of doing this manually I would recommend using the built in lightweight JavaScriptSerializer. No attributes are required on the classes you want to serialize/deserialize.
It's also more flexible and faster than the DataContractJsonSerializer, since it does not have to care about all the wcf stuff. Additionally it has generic overloads that make it very simple to use AND it can also handle anonymous types.
Serialization:
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var objectAsJsonString = serializer.Serialize(objectToSerialize);
Deserialization:
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
JsonFeaturedOffer deserializedObject = serializer.Deserialize<JsonFeaturedOffer>(s_JsonBaseDate);
To make it even easier you can create Extension methods that will give you json serialization/deserialization directly on the objects/strings.
If you want the class to auto-magically serialize into json/xml or deserialize in the object you need to decorate it with some serializable attributes:
[Serializable, XmlRoot("JsonFeaturedOffer"), DataContract(Name="JsonFeaturedOffer")]
public class JsonFeaturedOffer
{
[XmlElement ("OfferId"), DataMember(Name="OfferId")]
public string OfferId {get; set;}
... and so on
If this is an array of arrays of JsonFeaturedOffers, shouldn't it be:
byte[] byteArray = Encoding.ASCII.GetBytes(HdnJsonData.Value);
MemoryStream stream = new MemoryStream(byteArray);
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(JsonFeaturedOffer[][]));
object result= serializer.ReadObject(stream);
JsonFeaturedOffer[][] jsonObj = result as JsonFeaturedOffer[][];

Categories

Resources