Can I fail to deserialize with XmlSerializer in C# if an element is not found?
I am using XmlSerializer to write and read an object to xml in C#. I currently use the attributes XmlElement
and XmlIgnore
to manipulate the serialization of the object.
If my xml file is missing an xml element that I require, my object still deserializes (xml -> object) just fine. How do I indicate (preferably via Attributes) that a certain field is "required"?
Here is a sample method of what I am using currently:
[XmlElement(ElementName="numberOfWidgets")]
public int NumberThatIsRequired {
set ...;
get ...;
}
My ideal solution would be to add something like an XmlRequired
attribute.
Also, is there a good reference for what Attributes are available to manipulate the behavior of XmlSerializer?
Solution 1:
The only way I've found to do this is via XSD. What you can do is validate while you deserialize:
static T Deserialize<T>(string xml, XmlSchemaSet schemas)
{
//List<XmlSchemaException> exceptions = new List<XmlSchemaException>();
ValidationEventHandler validationHandler = (s, e) =>
{
//you could alternatively catch all the exceptions
//exceptions.Add(e.Exception);
throw e.Exception;
};
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(schemas);
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += validationHandler;
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (StringReader sr = new StringReader(xml))
using (XmlReader books = XmlReader.Create(sr, settings))
return (T)serializer.Deserialize(books);
}
Solution 2:
I've got an answer for the second part: "Attributes that control XML serialization".
Still investigating the first part...
EDIT: I strongly suspect you can't do this through XML deserialization itself. I've just run xsd.exe on a sample schema which includes a required attribute - and it's exactly the same if the attribute is marked as being optional. If there were a way of requiring properties to be set, I'd expect it to be implemented in that case.
I suspect you've basically got to just validate your tree of objects after deserializing it. Sorry about that...
Solution 3:
For extensibility reasons, XmlSerializer
is very forgiving when it comes to deserialization; things like [DefaultValue]
, ShouldSerialize{Foo}
and {Foo}Specified
are mainly used during serialization (the exception being {Foo}Specified
, which is set during deserialization as well as queried during serialization).
As such; there isn't an easy way to do this, unless you implement IXmlSerializable
and do it yourself. Richard shows an xsd option, which is also an option.