Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I specify DataContractSerializer EmitDefaultValue = false globally through app.config or web.config or some other means?

Tags:

c#

xml

asp.net

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.

Question

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.

  • Can this be specified in app.config/web.config?
  • Or, can it be set on the DataContractSerializer instance?

If this doesn't exist, it seems like a HUGE oversight by Microsoft.

like image 786
crush Avatar asked May 06 '14 17:05

crush


People also ask

What is EmitDefaultValue C#?

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.

Which attribute specifies that a public property of a class is capable of being serialized a Datacontract B serializable C DataMember D JSON element?

Data contract: It specifies that your entity class is ready for Serialization process.

What is Datacontract and DataMember in C#?

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.

What does the Datacontract attribute do?

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.


1 Answers

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"/>
like image 158
Leonid Vasilev Avatar answered Sep 24 '22 23:09

Leonid Vasilev