I'm trying to use XmlAttributeOverrides
to change the way my class is being serialized to XML. I need to exclude some properties and include others in a specific order.
I have this code here:
// XML Attribute Overrrides
public static XmlAttributeOverrides GetXMLAttributeOverrides(Type theType, List<string> propertiesToInlcudeInOrder, List<string> allColumnNames)
{
try
{
if (propertiesToInlcudeInOrder != null)
{
XmlAttributeOverrides theXMLAttributeOverrides = new XmlAttributeOverrides();
if (propertiesToInlcudeInOrder.Count > 0)
{
XmlAttributes mainNewXMLAttributes = new XmlAttributes();
mainNewXMLAttributes.XmlIgnore = false;
XmlAttributes ignoreXMLAttributes = new XmlAttributes();
ignoreXMLAttributes.XmlIgnore = true;
List<string> propertiesToNotInclude = new List<string>();
foreach (string theColumnName in allColumnNames)
{
string thePropertyName = theColumnName;
bool addProperty = true;
foreach (string propertyToInclude in propertiesToInlcudeInOrder)
{
if (thePropertyName == propertyToInclude)
{
addProperty = false;
break;
}
}
if (addProperty)
{
propertiesToNotInclude.Add(thePropertyName);
}
}
// To Ignore
foreach (string propertyNameToNotInlcude in propertiesToNotInclude)
{
XmlElementAttribute theXMLElementAttributeToAdd = new XmlElementAttribute(propertyNameToNotInlcude);
theXMLElementAttributeToAdd.ElementName = propertyNameToNotInlcude;
ignoreXMLAttributes.XmlElements.Add(theXMLElementAttributeToAdd);
theXMLAttributeOverrides.Add(theType, propertyNameToNotInlcude, ignoreXMLAttributes);
}
// To Add In Order
int counter = 1;
foreach (string propertyNameToIncludeInOrder in propertiesToInlcudeInOrder)
{
XmlElementAttribute theXMLElementAttributeToAdd = new XmlElementAttribute(propertyNameToIncludeInOrder);
theXMLElementAttributeToAdd.ElementName = propertyNameToIncludeInOrder;
theXMLElementAttributeToAdd.Order = counter;
mainNewXMLAttributes.XmlElements.Add(theXMLElementAttributeToAdd);
theXMLAttributeOverrides.Add(theType, propertyNameToIncludeInOrder, mainNewXMLAttributes);
counter++;
}
}
return theXMLAttributeOverrides;
}
else
{
return null;
}
}
catch (Exception ex)
{
MessageBox.Show("Error at 'GetXMLAttributeOverrides'" + Environment.NewLine + Environment.NewLine + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return null;
}
}
In my test I have a class with 13 properties and I want to include 3 in a specific order and exclude all the others.
I have made sure that I don't have any duplicates in my lists. I have double checked that I don't have the same property name in the 'Ignore List' and the 'Include List'. I get an exception on this line of my code: XmlSerializer(dataToSerialize.GetType(), allXMLAttribueOverrides);
allXMLAttribueOverrides
Is returned from my method GetXMLAttributeOverrides
The exception is:
There was an error reflecting type 'System.Collections.Generic.List`1[SystemName.UserControls.TestMain]'.
Inner exception is:
There was an error reflecting property 'TextColumn'.
You need to add XmlChoiceIdentifierAttribute to the 'TextColumn' member.
'TextColumn' is the first property in my test class
Here's my test code:
TestMain testItem = new TestMain(null, "TextColumnTEST", 5, Convert.ToDecimal(0.333), Convert.ToDecimal(0.777), DateTime.Now, "12:00:00", DateTime.Now, true, "Password", "#FFFFFF", null, null, null);
List<TestMain> dataToSerialize = new List<TestMain>();
dataToSerialize.Add(testItem);
List<string> propertiesToInlcudeInOrder = new List<string>();
propertiesToInlcudeInOrder.Add("CurrencyColumn");
propertiesToInlcudeInOrder.Add("NumberColumn");
propertiesToInlcudeInOrder.Add("TextColumn");
List<string> allColumnNames = new List<string>();
allColumnNames.Add("ID");
allColumnNames.Add("Select");
allColumnNames.Add("TextColumn");
allColumnNames.Add("NumberColumn");
allColumnNames.Add("CurrencyColumn");
allColumnNames.Add("DecimalColumn");
allColumnNames.Add("DateColumn");
allColumnNames.Add("TimeColumn");
allColumnNames.Add("DateAndTimeColumn");
allColumnNames.Add("YesNoColumn");
allColumnNames.Add("PasswordColumn");
allColumnNames.Add("ColorColumn");
allColumnNames.Add("ImageColumn");
allColumnNames.Add("DocumentColumn");
allColumnNames.Add("OtherColumn");
XmlAttributeOverrides allXMLAttribueOverrides = ReportingManipulation.GetXMLAttributeOverrides(dataToSerialize[0].GetType(), propertiesToInlcudeInOrder, allColumnNames);
using (StringWriter mainStringWriter = new StringWriter())
{
XmlSerializer mainXMLSerializer = new XmlSerializer(dataToSerialize.GetType(), allXMLAttribueOverrides);
mainXMLSerializer.Serialize(mainStringWriter, dataToSerialize);
return mainStringWriter.ToString();
}
and here's my test class:
public class TestMain
{
#region Properties
// Properties
[XmlIgnore]
public int? ID { get; set; }
[XmlIgnore]
public bool Select { get; set; }
public string TextColumn { get; set; }
public int NumberColumn { get; set; }
public decimal CurrencyColumn { get; set; }
public decimal DecimalColumn { get; set; }
public DateTime DateColumn { get; set; }
public string TimeColumn { get; set; }
public DateTime DateAndTimeColumn { get; set; }
public bool YesNoColumn { get; set; }
public string PasswordColumn { get; set; }
public string ColorColumn { get; set; }
public byte[] ImageColumn { get; set; }
public byte[] DocumentColumn { get; set; }
public byte[] OtherColumn { get; set; }
#endregion
#region Constructors
// Constructors
public TestMain()
{
try
{
}
catch (Exception ex)
{
MessageBox.Show("Error at Constructor: 'TestMain'" + Environment.NewLine + Environment.NewLine + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
public TestMain(int? theID, string theTextColumn, int theNumberColumn, decimal theCurrencyColumn, decimal theDecimalColumn, DateTime theDateColumn, string theTimeColumn, DateTime theDateAndTimeColumn, bool theYesNoColumn, string thePasswordColumn, string theColorColumn, byte[] theImageColumn, byte[] theDocumentColumn, byte[] theOtherColumn)
{
try
{
this.ID = theID;
this.TextColumn = theTextColumn;
this.NumberColumn = theNumberColumn;
this.CurrencyColumn = theCurrencyColumn;
this.DecimalColumn = theDecimalColumn;
this.DateColumn = theDateColumn;
this.TimeColumn = theTimeColumn;
this.DateAndTimeColumn = theDateAndTimeColumn;
this.YesNoColumn = theYesNoColumn;
this.PasswordColumn = thePasswordColumn;
this.ColorColumn = theColorColumn;
this.ImageColumn = theImageColumn;
this.DocumentColumn = theDocumentColumn;
this.OtherColumn = theOtherColumn;
}
catch (Exception ex)
{
MessageBox.Show("Error at Constructor: 'TestMain'" + Environment.NewLine + Environment.NewLine + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
#endregion
}
Where am I going wrong?
Any help / advice would be appreciated.