Deserializing XML time to datetime? - c#

I Have a third party XML file that I need to deserialize into objects but when I do so I get an error: string was not recognized as a valid datetime. This is because the time in XML is just that a time, in the format HH:mm:SS and the classes that were Generated from the XSD from the third party produce a datetime field that expects a date time not just a time.
they give me the xml:
<PO>
...
<PurchaseOrderTime>8:00:00</PurchaseOrderTime>
...
</PO>
The Generated class creates a System.DateTime object to hold the deserialized PurchaseOrderTime but fails due to it expecting a format along the lines of yyyy/MM/dd HH:mm:SS tt but as I have no control over what they send me xsd or xml, what can I do to fix this?
Is there a way to pre-process the field to get what I need?
Do I have to manually change the System.DateTime to a timespan(there is more than just this one time field otherwise I would have just done that)
What is the best way to do this?
Edit 1:
Here is the generated class from the XSD
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.1015")]
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.spscommerce.com/RSX")]
[System.Xml.Serialization.XmlRootAttribute("OrderHeader", Namespace="http://www.spscommerce.com/RSX", IsNullable=false)]
public partial class OrderHeaderType : System.ComponentModel.INotifyPropertyChanged {
...
private System.DateTime purchaseOrderTimeField;
private bool purchaseOrderTimeFieldSpecified;
...
[System.Xml.Serialization.XmlElementAttribute(DataType="time", Order=7)]
public System.DateTime PurchaseOrderTime {
get {
return this.purchaseOrderTimeField;
}
set {
if ((purchaseOrderTimeField.Equals(value) != true)) {
this.purchaseOrderTimeField = value;
this.OnPropertyChanged("PurchaseOrderTime");
}
}
}
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool PurchaseOrderTimeSpecified {
get {
return this.purchaseOrderTimeFieldSpecified;
}
set {
if ((purchaseOrderTimeFieldSpecified.Equals(value) != true)) {
this.purchaseOrderTimeFieldSpecified = value;
this.OnPropertyChanged("PurchaseOrderTimeSpecified");
}
}
}
#region Serialize/Deserialize
/// <summary>
/// Serializes current OrderHeaderType object into an XML document
/// </summary>
/// <returns>string XML value</returns>
public virtual string Serialize() {
System.IO.StreamReader streamReader = null;
System.IO.MemoryStream memoryStream = null;
try {
memoryStream = new System.IO.MemoryStream();
Serializer.Serialize(memoryStream, this);
memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
streamReader = new System.IO.StreamReader(memoryStream);
return streamReader.ReadToEnd();
}
finally {
if ((streamReader != null)) {
streamReader.Dispose();
}
if ((memoryStream != null)) {
memoryStream.Dispose();
}
}
}
/// <summary>
/// Deserializes workflow markup into an OrderHeaderType object
/// </summary>
/// <param name="xml">string workflow markup to deserialize</param>
/// <param name="obj">Output OrderHeaderType object</param>
/// <param name="exception">output Exception value if deserialize failed</param>
/// <returns>true if this XmlSerializer can deserialize the object; otherwise, false</returns>
public static bool Deserialize(string xml, out OrderHeaderType obj, out System.Exception exception) {
exception = null;
obj = default(OrderHeaderType);
try {
obj = Deserialize(xml);
return true;
}
catch (System.Exception ex) {
exception = ex;
return false;
}
}
public static bool Deserialize(string xml, out OrderHeaderType obj) {
System.Exception exception = null;
return Deserialize(xml, out obj, out exception);
}
public static OrderHeaderType Deserialize(string xml) {
System.IO.StringReader stringReader = null;
try {
stringReader = new System.IO.StringReader(xml);
return ((OrderHeaderType)(Serializer.Deserialize(System.Xml.XmlReader.Create(stringReader))));
}
finally {
if ((stringReader != null)) {
stringReader.Dispose();
}
}
}
}
/// <summary>
/// Deserializes xml markup from file into an OrderHeaderType object
/// </summary>
/// <param name="fileName">string xml file to load and deserialize</param>
/// <param name="obj">Output OrderHeaderType object</param>
/// <param name="exception">output Exception value if deserialize failed</param>
/// <returns>true if this XmlSerializer can deserialize the object; otherwise, false</returns>
public static bool LoadFromFile(string fileName, out OrderHeaderType obj, out System.Exception exception) {
exception = null;
obj = default(OrderHeaderType);
try {
obj = LoadFromFile(fileName);
return true;
}
catch (System.Exception ex) {
exception = ex;
return false;
}
}
public static bool LoadFromFile(string fileName, out OrderHeaderType obj) {
System.Exception exception = null;
return LoadFromFile(fileName, out obj, out exception);
}
public static OrderHeaderType LoadFromFile(string fileName) {
System.IO.FileStream file = null;
System.IO.StreamReader sr = null;
try {
file = new System.IO.FileStream(fileName, FileMode.Open, FileAccess.Read);
sr = new System.IO.StreamReader(file);
string xmlString = sr.ReadToEnd();
sr.Close();
file.Close();
return Deserialize(xmlString);
}
finally {
if ((file != null)) {
file.Dispose();
}
if ((sr != null)) {
sr.Dispose();
}
}
}
#endregion
}

I Ended up doing a few things,
I used a refactoring tool to change all DateTimes in the generated classes to strings and and wrote the code in a way that it would work as if the DateTime was a string. (while this may not be optimal it works!)
Asked the people who generated the xml to fix the generated xml file. so that when/if I get a new file I can just regenerate the classes from the XSD and use the DateTime fields as expected.
While programing around this issue with strings was not the best thing, It should work either way and until I get a file that processes correctly I will just use the refactoring tool to change all DateTime's to strings.

If your user gives you a document which does not validate against the schema, XSD2Code is likely to have trouble with it. Throw it back at the user and tell them to fix it. Or parse the document and interpret it yourself, so you can write your own code to decide how to recover from questionable cases.
If the document does validate against the schema but XSD2Code can't handle it, complain to the authors of XSD2Code and get it fixed, or replace it with something which doesn't have the same bug/limitation. Which may, again, mean writing your own code.
If XSD2Code can handle it but C#'s provided code can't, you need to either go looking for code that can handle it (suggested websearch: c# parse iso 8601), or write your own.

Related

SOAP stream not initialising after upgrading to .NET 4.6 from 4.0

After upgrading the environment to target the .NET 4.6 framework from .NET 4.0, when AuditSoap is externally called it is referencing a null requestSoapMessage object due to what appears to be the ChainStream procedure not being initialised.
Does .NET 4.6 handle SOAP differently than previous versions of the framework? When I step through the code on .NET 4.0 it works as intended, with the ChainStream procedure being initialised (which then calls ProcessMessage). This doesn't happen on .NET 4.6 - the code base has not changed between upgrades so I believe the issue must reside with how .NET 4.6 handles it.
private static XmlDocument xmlRequest;
/// Gets the outgoing XML request
public static XmlDocument XmlRequest
{ get { return xmlRequest; } }
private static XmlDocument xmlResponse;
/// Gets the incoming XML response
public static XmlDocument XmlResponse
{ get { return xmlResponse; } }
private static SoapMessage requestSoapMessage;
/// Gets the outgoing soap message
public static SoapMessage RequestSoapMessage
{ get { return requestSoapMessage; } }
private static SoapMessage responseSoapMessage;
/// Gets the incoming soap message
public static SoapMessage ResponseSoapMessage
{ get { return responseSoapMessage; } }
/// Save the Stream representing the SOAP request
/// or SOAP response into a local memory buffer.
public override Stream ChainStream(Stream stream)
{
oldStream = stream;
newStream = new MemoryStream();
return newStream;
}
/// If the SoapMessageStage is such that the SoapRequest or
/// SoapResponse is still in the SOAP format to be sent or received,
/// save it to the xmlRequest or xmlResponse property.
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
xmlRequest = GetSoapEnvelope(newStream);
CopyStream(newStream, oldStream);
requestSoapMessage = message;
break;
case SoapMessageStage.BeforeDeserialize:
CopyStream(oldStream, newStream);
xmlResponse = GetSoapEnvelope(newStream);
responseSoapMessage = message;
break;
case SoapMessageStage.AfterDeserialize:
break;
}
}
public void AuditSoap()
{
try
{
string action = System.Web.HttpContext.Current.Request.RequestContext.RouteData.GetRequiredString("action");
//log the Request
logService.Audit(true,
LogArea.Data,
requestSoapMessage.MethodInfo.Name,
"Request",
action,
XmlRequest.InnerXml,
null,
null,
null,
XmlRequest.InnerXml);
//log the response
logService.Audit(true,
LogArea.Data,
responseSoapMessage.MethodInfo.Name,
"Response",
action,
XmlResponse.InnerXml,
null,
null,
null,
XmlResponse.InnerXml);
}
catch (Exception ex)
{
Trace.TraceError("Error in logging the web service.\n{0}", ex.ToJson());
}
}
/// Returns the XML representation of the Soap Envelope in the supplied stream.
/// Resets the position of stream to zero.
private XmlDocument GetSoapEnvelope(Stream stream)
{
XmlDocument xml = new XmlDocument();
stream.Position = 0;
StreamReader reader = new StreamReader(stream);
xml.LoadXml(reader.ReadToEnd());
stream.Position = 0;
return xml;
}
/// Copies a stream.
private void CopyStream(Stream from, Stream to)
{
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}
/// Included only because it must be implemented.
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
return null;
}
/// Included only because it must be implemented.
public override object GetInitializer(Type WebServiceType)
{
return null;
}
/// Included only because it must be implemented.
public override void Initialize(object initializer)
{
}

populating list collection from xml

I have the following xsd and generated a .net class from it. I need to read the xml file and populate the Questions and Answers in the .Net class. I also need to access the SubQuestionAnswer\Question and SubQuestionAnswer\Answer nodes and assign it to qa.SubQuestions.SubQuestion and qa.SubQuestions.SubAnswer respectively.Could someone let me know if my code will work. The logic of looping through the xmlnodes and looping through the list to assign node values.
XSD file
<xs:complexType name="Fatca">
<xs:sequence>
<xs:element name="AccountNumber" type="xs:string"/>
<xs:element name="Questionnaire" type="FatcaQuestions" maxOccurs="unbounded" minOccurs="1"/>
<xs:element name="ContactDetails" type="ContactDetails"/>
<xs:element name="AccountDetails" type="AccountDetailsBasic" />
<xs:element name="Request" type="GeneralAccountId" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="FatcaQuestions">
<xs:sequence>
<xs:element name="Question" type="xs:string" />
<xs:element name="Answer" type="xs:string" />
<xs:element name="SubQuestions" type="FatcaSubQuestions" maxOccurs="1" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="FatcaSubQuestions">
<xs:sequence>
<xs:element name="SubQuestion" type="xs:string" />
<xs:element name="SubAnswer" type="xs:string" />
</xs:sequence>
</xs:complexType>
Following is the class generated from this xsd
public partial class Fatca
{
private string accountNumberField;
private List<FatcaQuestions> questionnaireField;
private ContactDetails contactDetailsField;
private AccountDetailsBasic accountDetailsField;
private GeneralAccountId requestField;
private static System.Xml.Serialization.XmlSerializer serializer;
public Fatca()
{
this.requestField = new GeneralAccountId();
this.accountDetailsField = new AccountDetailsBasic();
this.contactDetailsField = new ContactDetails();
this.questionnaireField = new List<FatcaQuestions>();
}
public string AccountNumber
{
get
{
return this.accountNumberField;
}
set
{
this.accountNumberField = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("Questionnaire")]
public List<FatcaQuestions> Questionnaire
{
get
{
return this.questionnaireField;
}
set
{
this.questionnaireField = value;
}
}
public ContactDetails ContactDetails
{
get
{
return this.contactDetailsField;
}
set
{
this.contactDetailsField = value;
}
}
public AccountDetailsBasic AccountDetails
{
get
{
return this.accountDetailsField;
}
set
{
this.accountDetailsField = value;
}
}
public GeneralAccountId Request
{
get
{
return this.requestField;
}
set
{
this.requestField = value;
}
}
private static System.Xml.Serialization.XmlSerializer Serializer
{
get
{
if ((serializer == null))
{
serializer = new System.Xml.Serialization.XmlSerializer(typeof(Fatca));
}
return serializer;
}
}
#region Serialize/Deserialize
/// <summary>
/// Serializes current Fatca object into an XML document
/// </summary>
/// <returns>string XML value</returns>
public virtual string Serialize()
{
System.IO.StreamReader streamReader = null;
System.IO.MemoryStream memoryStream = null;
try
{
memoryStream = new System.IO.MemoryStream();
Serializer.Serialize(memoryStream, this);
memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
streamReader = new System.IO.StreamReader(memoryStream);
return streamReader.ReadToEnd();
}
finally
{
if ((streamReader != null))
{
streamReader.Dispose();
}
if ((memoryStream != null))
{
memoryStream.Dispose();
}
}
}
public static bool Deserialize(string xml, out Fatca obj, out System.Exception exception)
{
exception = null;
obj = default(Fatca);
try
{
obj = Deserialize(xml);
return true;
}
catch (System.Exception ex)
{
exception = ex;
return false;
}
}
public static bool Deserialize(string xml, out Fatca obj)
{
System.Exception exception = null;
return Deserialize(xml, out obj, out exception);
}
public static Fatca Deserialize(string xml)
{
System.IO.StringReader stringReader = null;
try
{
stringReader = new System.IO.StringReader(xml);
return ((Fatca)(Serializer.Deserialize(System.Xml.XmlReader.Create(stringReader))));
}
finally
{
if ((stringReader != null))
{
stringReader.Dispose();
}
}
}
/// <summary>
/// Serializes current Fatca object into file
/// </summary>
/// <param name="fileName">full path of outupt xml file</param>
/// <param name="exception">output Exception value if failed</param>
/// <returns>true if can serialize and save into file; otherwise, false</returns>
public virtual bool SaveToFile(string fileName, out System.Exception exception)
{
exception = null;
try
{
SaveToFile(fileName);
return true;
}
catch (System.Exception e)
{
exception = e;
return false;
}
}
public virtual void SaveToFile(string fileName)
{
System.IO.StreamWriter streamWriter = null;
try
{
string xmlString = Serialize();
System.IO.FileInfo xmlFile = new System.IO.FileInfo(fileName);
streamWriter = xmlFile.CreateText();
streamWriter.WriteLine(xmlString);
streamWriter.Close();
}
finally
{
if ((streamWriter != null))
{
streamWriter.Dispose();
}
}
}
/// <summary>
/// Deserializes xml markup from file into an Fatca object
/// </summary>
/// <param name="fileName">string xml file to load and deserialize</param>
/// <param name="obj">Output Fatca object</param>
/// <param name="exception">output Exception value if deserialize failed</param>
/// <returns>true if this XmlSerializer can deserialize the object; otherwise, false</returns>
public static bool LoadFromFile(string fileName, out Fatca obj, out System.Exception exception)
{
exception = null;
obj = default(Fatca);
try
{
obj = LoadFromFile(fileName);
return true;
}
catch (System.Exception ex)
{
exception = ex;
return false;
}
}
public static bool LoadFromFile(string fileName, out Fatca obj)
{
System.Exception exception = null;
return LoadFromFile(fileName, out obj, out exception);
}
public static Fatca LoadFromFile(string fileName)
{
System.IO.FileStream file = null;
System.IO.StreamReader sr = null;
try
{
file = new System.IO.FileStream(fileName, FileMode.Open, FileAccess.Read);
sr = new System.IO.StreamReader(file);
string xmlString = sr.ReadToEnd();
sr.Close();
file.Close();
return Deserialize(xmlString);
}
finally
{
if ((file != null))
{
file.Dispose();
}
if ((sr != null))
{
sr.Dispose();
}
}
}
#endregion
}
public partial class FatcaQuestions
{
private string questionField;
private string answerField;
private FatcaSubQuestions subQuestionsField;
private static System.Xml.Serialization.XmlSerializer serializer;
public FatcaQuestions()
{
this.subQuestionsField = new FatcaSubQuestions();
}
public string Question
{
get
{
return this.questionField;
}
set
{
this.questionField = value;
}
}
public string Answer
{
get
{
return this.answerField;
}
set
{
this.answerField = value;
}
}
public FatcaSubQuestions SubQuestions
{
get
{
return this.subQuestionsField;
}
set
{
this.subQuestionsField = value;
}
}
private static System.Xml.Serialization.XmlSerializer Serializer
{
get
{
if ((serializer == null))
{
serializer = new System.Xml.Serialization.XmlSerializer(typeof(FatcaQuestions));
}
return serializer;
}
}
#region Serialize/Deserialize
/// <summary>
/// Serializes current FatcaQuestions object into an XML document
/// </summary>
/// <returns>string XML value</returns>
public virtual string Serialize()
{
System.IO.StreamReader streamReader = null;
System.IO.MemoryStream memoryStream = null;
try
{
memoryStream = new System.IO.MemoryStream();
Serializer.Serialize(memoryStream, this);
memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
streamReader = new System.IO.StreamReader(memoryStream);
return streamReader.ReadToEnd();
}
finally
{
if ((streamReader != null))
{
streamReader.Dispose();
}
if ((memoryStream != null))
{
memoryStream.Dispose();
}
}
}
/// <summary>
/// Deserializes workflow markup into an FatcaQuestions object
/// </summary>
/// <param name="xml">string workflow markup to deserialize</param>
/// <param name="obj">Output FatcaQuestions object</param>
/// <param name="exception">output Exception value if deserialize failed</param>
/// <returns>true if this XmlSerializer can deserialize the object; otherwise, false</returns>
public static bool Deserialize(string xml, out FatcaQuestions obj, out System.Exception exception)
{
exception = null;
obj = default(FatcaQuestions);
try
{
obj = Deserialize(xml);
return true;
}
catch (System.Exception ex)
{
exception = ex;
return false;
}
}
public static bool Deserialize(string xml, out FatcaQuestions obj)
{
System.Exception exception = null;
return Deserialize(xml, out obj, out exception);
}
public static FatcaQuestions Deserialize(string xml)
{
System.IO.StringReader stringReader = null;
try
{
stringReader = new System.IO.StringReader(xml);
return ((FatcaQuestions)(Serializer.Deserialize(System.Xml.XmlReader.Create(stringReader))));
}
finally
{
if ((stringReader != null))
{
stringReader.Dispose();
}
}
}
/// <summary>
/// Serializes current FatcaQuestions object into file
/// </summary>
/// <param name="fileName">full path of outupt xml file</param>
/// <param name="exception">output Exception value if failed</param>
/// <returns>true if can serialize and save into file; otherwise, false</returns>
public virtual bool SaveToFile(string fileName, out System.Exception exception)
{
exception = null;
try
{
SaveToFile(fileName);
return true;
}
catch (System.Exception e)
{
exception = e;
return false;
}
}
public virtual void SaveToFile(string fileName)
{
System.IO.StreamWriter streamWriter = null;
try
{
string xmlString = Serialize();
System.IO.FileInfo xmlFile = new System.IO.FileInfo(fileName);
streamWriter = xmlFile.CreateText();
streamWriter.WriteLine(xmlString);
streamWriter.Close();
}
finally
{
if ((streamWriter != null))
{
streamWriter.Dispose();
}
}
}
/// <summary>
/// Deserializes xml markup from file into an FatcaQuestions object
/// </summary>
/// <param name="fileName">string xml file to load and deserialize</param>
/// <param name="obj">Output FatcaQuestions object</param>
/// <param name="exception">output Exception value if deserialize failed</param>
/// <returns>true if this XmlSerializer can deserialize the object; otherwise, false</returns>
public static bool LoadFromFile(string fileName, out FatcaQuestions obj, out System.Exception exception)
{
exception = null;
obj = default(FatcaQuestions);
try
{
obj = LoadFromFile(fileName);
return true;
}
catch (System.Exception ex)
{
exception = ex;
return false;
}
}
public static bool LoadFromFile(string fileName, out FatcaQuestions obj)
{
System.Exception exception = null;
return LoadFromFile(fileName, out obj, out exception);
}
public static FatcaQuestions LoadFromFile(string fileName)
{
System.IO.FileStream file = null;
System.IO.StreamReader sr = null;
try
{
file = new System.IO.FileStream(fileName, FileMode.Open, FileAccess.Read);
sr = new System.IO.StreamReader(file);
string xmlString = sr.ReadToEnd();
sr.Close();
file.Close();
return Deserialize(xmlString);
}
finally
{
if ((file != null))
{
file.Dispose();
}
if ((sr != null))
{
sr.Dispose();
}
}
}
#endregion
}
Following is the program that is reading the xml file and populating the collection
XmlDocument xmlDocument = new XmlDocument();
var fataQuestionnaire = #"<?xml version=""1.0"" encoding=""UTF-16""?>
<FatcaQuestionnaire xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
<QuestionAnswers>
<QuestionAnswer>
<Question>What is your source of wealth?</Question>
<Answer>I am italian </Answer>
</QuestionAnswer>
<QuestionAnswer>
<Question>What is your occupation and name of employer?</Question>
<Answer>Bestinvest</Answer>
</QuestionAnswer>
<QuestionAnswer>
<Question>Do you have a business or residence in?</Question>
<Answer>Yes</Answer>
</QuestionAnswer>
<QuestionAnswer>
<Question>How long have you lived outside of Albania</Question>
<Answer>5 years</Answer>
</QuestionAnswer>
<QuestionAnswer>
<Question>Do you return to Albania on a regular basis</Question>
<Answer>Yes</Answer>
<SubQuestionAnswer>
<Question>How frequently?</Question>
<Answer>every year</Answer>
</SubQuestionAnswer>
</QuestionAnswer>
<QuestionAnswer>
<Question>Do you have family in Albania?</Question>
<Answer>Yes</Answer>
<SubQuestionAnswer>
<Question>Family relationship?</Question>
<Answer>My parents lives there</Answer>
</SubQuestionAnswer>
</QuestionAnswer>
<QuestionAnswer>
<Question>Are you connected to the government of Albania?</Question>
<Answer>Yes</Answer>
<SubQuestionAnswer>
<Question>Nature of association</Question>
<Answer>I was an ex minister</Answer>
</SubQuestionAnswer>
</QuestionAnswer>
<QuestionAnswer>
<Question>Do you send or receive money from Albania?</Question>
<Answer>Yes</Answer>
<SubQuestionAnswer>
<Question>How often and why?</Question>
<Answer>Every month for my parents to live with.</Answer>
</SubQuestionAnswer>
</QuestionAnswer>
</QuestionAnswers>
</FatcaQuestionnaire>";
XmlTextReader reader = new XmlTextReader(new StringReader(fataQuestionnaire));
xmlDocument.Load(reader);
XmlElement xmlRoot = xmlDocument.DocumentElement;
if (xmlRoot != null)
{
XmlNodeList xnlNodes = xmlRoot.SelectNodes("/FatcaQuestionnaire/QuestionAnswers/QuestionAnswer");
foreach (XmlNode xndNode in xnlNodes)
{
foreach (var qa in fatca.Questionnaire)
{
if (xndNode["Question"] != null)
qa.Question = xndNode["Question"].InnerText;
if (xndNode["Answer"] != null)
qa.Answer = xndNode["Answer"].InnerText;
}
}
you can simply use the XML serialization and deserialization methods that are in the generated class, use the Deserialize method to deserialize a Facta object from your XML, you don't need to write those XML loops.

Edit Object with xml without creating new Instance

I have a class which needs to be a Singleton.
It must also be able to load and save its field data in an xml file.
The following method will return a new instance, which breaks my Singleton pattern, leaving potential bugs in my code.
public Settings Load()
{
using (Stream stream = File.OpenRead(FileName))
{
XmlSerializer serializer = new XmlSerializer(typeof(Settings));
return (Settings)serializer.Deserialize(stream);
}
}
What method can I use in order to update the data in my existing instance, instead of returning a entirely new instance?
I've studied a bit of Linq to Xml, but haven't found any good example of this.
Is it necessary for me to keep all my field data in a Dictionary?
I used to run into all sorts of bugs making an Xml Singleton class and ended up scrapping it as I had handles all over the place. I replaced it with using two ways. One a read-only version that was for reading data, and a second Using method/statement for writing changes.
This in general is the pattern I use:
public class Settings : IDisposable
{
string file = "my settings file";
XElement root;
private Settings()
{
root = XElement.Load(file);
}
private void Dispose()
{
root.Save(file);
}
public static Settings Read { get { return new Settings(); } } // return read-only version
public static void Write(Action<Settings> handler)
{
using(Setting settings = new Settings())
handler(settings);
}
// below here is implentation specific
public XElement Root { get { return root; } }
public string SettingA
{
get { return (string)(Root.Attribute("SettingA") ?? (object)string.Empty); }
set { Set(Root, "SettingsA", value, true); }
}
// I wrote this for another StackOverflow thread
/// <summary>
/// Set any value via its .ToString() method.
/// <para>Returns XElement of source or the new XElement if is an ELEMENT</para>
/// </summary>
/// <param name="isAttribute">true for ATTRIBUTE or false for ELEMENT</param>
/// <returns>source or XElement value</returns>
private XElement Set(XElement source, string name, object value, bool isAttribute)
{
string sValue = value.ToString();
XElement eValue = source.Element(name), result = source;
XAttribute aValue = source.Attribute(name);
if (null != eValue)
eValue.ReplaceWith(result = new XElement(name, sValue));
else if (null != aValue)
aValue.ReplaceWith(new XAttribute(name, sValue));
else if (isAttribute)
source.Add(new XAttribute(name, sValue));
else
source.Add(result = new XElement(name, sValue));
return result;
}
/// <summary>
/// Replace with for XAttribute
/// </summary>
/// <param name="source"></param>
/// <param name="value"></param>
/// <returns></returns>
public static XAttribute ReplaceWith(this XAttribute source, XAttribute value)
{
XElement parent = source.Parent;
if (null == parent)
throw new Exception("Source has no parent");
source.Remove();
parent.Add(value);
return value;
}
}
I've not used the serializer, so don't know if my pattern will fit for you. I prefer XElement.
So to use this you'd probably write a singleton class that makes use of your non-singleton XmlSerialize class. You'd only access it through the singleton.
But this is how I'd end up using it as is:
string settingA = Settings.Read.SettingA;
To save a value it would be:
Settings.Write(s => s.SettingA = "new value");
why dont you have something like
public Class TheClassHoldingYourObject
{
private static XmlSerializer _instance;
public static Settings Load()
{
if(_instance != null) return _instance
using (Stream stream = File.OpenRead(FileName))
{
XmlSerializer serializer = new XmlSerializer(typeof(Settings));
return (Settings)serializer.Deserialize(stream);
}
}
}
Now you will always get the same instance

Using autogenerated proxy class from XSD (.Net C# 4.0)

I've used xsd.exe to generate a proxy class called "FacturaE".
I can instantiate this class, fill it information, and save to XML with XmlSerializer.
But, given a XML file, well formatted, how can I read it into a "FacturaE"?
Thanks
As a replacement for xsd.exe, Xsd2Code is a much more fully featured class generator. It can add methods to the generated classes to both serialize, and deserialize from Xml.
Following is an example of the serialize/deserialize methods generated by Xsd2Code:
/// <summary>
/// Serializes current EntityBase object into an XML document
/// </summary>
// <returns>string XML value</returns>
public virtual string Serialize() {
System.IO.StreamReader streamReader = null;
System.IO.MemoryStream memoryStream = null;
try {
memoryStream = new System.IO.MemoryStream();
Serializer.Serialize(memoryStream, this);
memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
streamReader = new System.IO.StreamReader(memoryStream);
return streamReader.ReadToEnd();
}
finally {
if (streamReader != null) {
streamReader.Dispose();
}
if (memoryStream != null) {
memoryStream.Dispose();
}
}
}
/// <summary>
/// Deserializes workflow markup into an EntityBase object
/// </summary>
// <param name="xml">string workflow markup to deserialize</param>
// <param name="obj">Output EntityBase object</param>
// <param name="exception">output Exception value if deserialize failed</param>
// <returns>true if this XmlSerializer can deserialize the object; otherwise, false</returns>
public static bool Deserialize(string xml, out T obj, out System.Exception exception) {
exception = null;
obj = default(T);
try {
obj = Deserialize(xml);
return true;
}
catch (System.Exception ex) {
exception = ex;
return false;
}
}
public static bool Deserialize(string xml, out T obj) {
System.Exception exception = null;
return Deserialize(xml, out obj, out exception);
}
public static T Deserialize(string xml) {
System.IO.StringReader stringReader = null;
try {
stringReader = new System.IO.StringReader(xml);
return ((T)(Serializer.Deserialize(System.Xml.XmlReader.Create(stringReader))));
}
finally {
if (stringReader != null) {
stringReader.Dispose();
}
}
}

How to send a System.IO.Stream casted to object using HTTP in WCF?

I have a very simple WCF program where I have a simple self-host and a client running on the same computer. There is a single method which returns a System.IO.Stream, which is actually a serialized form of a simple string. (This could be any number of data types, but for the time being let's take it as a string).
Following is the code I use if you want to take a look at. SerializeData() and DeserializeData() are methods used to do just that, and works fine.
Host Service:
namespace HelloWCF1
{
[ServiceContract(Namespace = "http://My.WCF.Samples")]
public interface IService1
{
[OperationContract]
Stream GetString();
}
public class Service1 : IService1
{
//Simple String
public Stream GetString()
{
string str = "ABC";
Stream ms = new MemoryStream();
SerializeData<string>(str, ms);
return ms;
}
/// <summary>
/// Serialize an object of the type T to a Stream
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="objectToSerialize"></param>
/// <param name="str"></param>
public void SerializeData<T>(T objectToSerialize, Stream str)
{
BinaryFormatter bf = new BinaryFormatter();
try
{
bf.Serialize(str, objectToSerialize);
str.Position = 0;
}
catch (Exception)
{
}
}
/// <summary>
/// Deserialize a Stream
/// </summary>
/// <param name="dataToDeserialize"></param>
/// <returns></returns>
public object DeserializeData(Stream dataToDeserialize)
{
BinaryFormatter bf = new BinaryFormatter();
object ret = null;
try
{
ret = bf.Deserialize(dataToDeserialize);
}
catch (Exception)
{
}
return ret;
}
}
class Program
{
static void Main(string[] args)
{
Uri baseAddr = new Uri("http://localhost:8000/WCFSampleService");
//ServiceHost is created by defining Service Type and Base Address
using (ServiceHost svcHost = new ServiceHost(typeof(Service1), baseAddr))
{
//Trace message for service start
Console.WriteLine("Service Starting...");
//Adding an end point
svcHost.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), "HelloWCF");
//Open service host
svcHost.Open();
Console.WriteLine("Press [Enter] to terminate.");
Console.ReadLine();
//Close service host
svcHost.Close();
}
}
}
}
Client Program:
namespace Client
{
[ServiceContract(Namespace = "http://My.WCF.Samples")]
public interface IService1
{
[OperationContract]
Stream GetString();
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private IService1 proxy = null;
private Stream memStr = new MemoryStream();
private void button1_Click(object sender, EventArgs e)
{
//Create end point
EndpointAddress epAddr = new EndpointAddress("http://localhost:8000/WCFSampleService/HelloWCF");
//Create proxy
proxy = ChannelFactory<IService1>.CreateChannel(new BasicHttpBinding(), epAddr);
//WCF Service Method is called to aquire the stream
try
{
memStr = proxy.GetString();
string str = (string)DeserializeData(memStr);
MessageBox.Show(str);
}
catch (CommunicationException commEx)
{
MessageBox.Show("Service Call Failed:" + commEx.Message);
}
}
/// <summary>
/// Serialize an object of the type T to a Stream
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="objectToSerialize"></param>
/// <param name="str"></param>
public static void SerializeData<T>(T objectToSerialize, Stream str)
{
BinaryFormatter bf = new BinaryFormatter();
try
{
bf.Serialize(str, objectToSerialize);
str.Position = 0;
}
catch (Exception)
{
}
}
/// <summary>
/// Deserialize a Stream
/// </summary>
/// <param name="dataToDeserialize"></param>
/// <returns></returns>
public static object DeserializeData(Stream dataToDeserialize)
{
BinaryFormatter bf = new BinaryFormatter();
object ret = null;
try
{
ret = bf.Deserialize(dataToDeserialize);
}
catch (Exception)
{
}
return ret;
}
}
}
Now, this works fine. It serializes a string into a Stream and sends using HTTP quite fine. However, I have a need to convert of cast this Stream into an object before sending. Simply put, I need the GetString() method to look like this:
public object GetString()
{
string str = "ABC";
Stream ms = new MemoryStream();
SerializeData<string>(str, ms);
return (object)ms;
}
However, when I do this, inside the Button1_Click event, at the line ***memStr = proxy.GetString();*** I get a CommunicationException. I work in a Japanese OS, so the exception message I get is in Japanese so I'll try to translate into English as best as I can. Forgive me if it is not very clear.
***Error occured in the reception of HTTP response concerning [url]http://localhost:8000/WCFSampleService/HelloWCF[/url]. Cause of the error could be Service End Point binding is not using an HTTP protocol. Or as a different cause, it is also possible that HTTP request context is suspended according to the server (as in the case of server being shut down). Please refer the server log for more details.***
What exactly is the problem and how can I get the program to work the way I want? It says to look at the log files but where can I find them?
Thanks in advance!
Would you not be better off just returning the string? Surely the string returned as a stream over an Http binding will be being Base64 encoded, which normally doubles the size of the data being returned!
Maybe you could consider TcpBinding as an alternative.

Categories

Resources