I have a very large class library with >100 POCO objects. I need to serialize these objects into XML to transmit to a REST service.
I've been trying to use DataContractSerializer
, but it outputs XML elements with i:nil="true"
for any properties that are null. This trips up the REST service to which I'm transmitting XML. Yes, I realize that it shouldn't. The service provider has informed me that correcting the issue will take months. I don't have months to wait for this service to work.
I've been digging through the documentation trying to find a way to suppress these nil objects from being transmitted. I'm aware that I could set the EmitDefaultValue property to false on each individual property of each POCO object. I'm not about to do that for more than 100 objects unless I have no other choice. Furthermore, I don't believe I should be forced to annotate my class library objects with DataContract attributes. I also don't want to mirror my class library with DataContractSurrogates. That is just obscene.
Surely, there is a configuration option somewhere where I can specify that the default behavior for serialization should be EmitDefaultValue = false
. I've been unable to find it though. I'm hoping someone else has found it, or has found another global option for suppressing the null properties from the XML.
DataContractSerializer
instance?If this doesn't exist, it seems like a HUGE oversight by Microsoft.
Gets or sets a value that specifies whether to serialize the default value for a field or property being serialized. public: property bool EmitDefaultValue { bool get(); void set(bool value); }; C# Copy.
Data contract: It specifies that your entity class is ready for Serialization process.
A datacontract is a formal agreement between a client and service that abstractly describes the data to be exchanged. In WCF, the most common way of serialization is to make the type with the datacontract attribute and each member as datamember.
By default, the DataContractSerializer infers the data contract and serializes all publicly visible types. All public read/write properties and fields of the type are serialized.
I believe that there is no official way to set this property globally, maybe because it's described as not recommended practice in most cases.
But there is workaround. You can define your own DataMemberAttribute
in System.Runtime.Serialization
namespace with EmitDefaultValue
set to false
by default. Put it somewhere in your project. And that's all you have to do. Compiler will give you a warning saying that your type conflict with imported one, but will use your type after all. I took this class from Microsoft sources, set EmitDefaultValue
to false
and replace exception throw in order check because it was using internal utility class:
namespace System.Runtime.Serialization
{
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public sealed class DataMemberAttribute : Attribute
{
string name;
bool isNameSetExplicitly;
int order = -1;
bool isRequired;
bool emitDefaultValue = false;
public string Name
{
get { return name; }
set { name = value; isNameSetExplicitly = true; }
}
public bool IsNameSetExplicitly
{
get { return isNameSetExplicitly; }
}
public int Order
{
get { return order; }
set
{
if (order < 0)
throw new InvalidDataContractException();
order = value;
}
}
public bool IsRequired
{
get { return isRequired; }
set { isRequired = value; }
}
public bool EmitDefaultValue
{
get { return emitDefaultValue; }
set { emitDefaultValue = value; }
}
}
}
Now if we take new Foo()
:
using System.Runtime.Serialization;
namespace FooBar
{
[DataContract]
public class Foo
{
// Warning about type conflict.
[DataMember]
public string Bar { get; set; }
}
}
It will be serialized by DataContractSerializer
as:
<Foo xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication1"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With