Q:

How to Ignore Null values while serializing OData response

I've a requirement to omit the null valued fields from the response altogether.
I can do this by modifying the JsonFormatter Serialization Setting for a normal webapi response.
config.Formatters.JsonFormatter.SerializationSettings
      .NullValueHandling = NullValueHandling.Ignore;

But that does not seem to work once i switch to OData.
Here are my files:
WebApi.config:
public static void Register(HttpConfiguration config)
{
    var builder = new ODataConventionModelBuilder();
    var workerEntitySet = builder.EntitySet<Item>("Values");
    config.Routes.MapODataRoute("Default", "api", builder.GetEdmModel());
}

Item Model:
public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string OptionalField { get; set; }
}

ValuesController:
public class ValuesController : EntitySetController<Item, int>
{
    public static List<Item> items = new List<Item>() 
    {
        new Item { Id = 1, Name = "name1", OptionalField = "Value Present" }, 
        new Item { Id = 3, Name = "name2" } 
    };
    [Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
    public override IQueryable<Item> Get()
    {
        return items.AsQueryable();
    }
    [Queryable]
    protected override Item GetEntityByKey(int  id)
    {
        return items.Single(i => i.Id == id);
    }
}

Here is the response I get for GET: api/Values. 
{
 "odata.metadata":"http://localhost:28776/api/$metadata#Values",
 "value":[
   {
     "Id":1,
     "Name":"name1",
     "OptionalField":"Value Present"
   },
   {
     "Id":3,
     "Name":"name2",
     "OptionalField":null
   }
  ]
}

But I do not need the elements with null values present in the response - in the response below, I need the "OptionalField" not to be present in the second item (As its value is null). I need to achieve it in my response, I do not want the users to query for non-null values only.

A:

In ODataLib v7 things changed drastically around these sorts of customisations thanks to Depencency Injection (DI)

This advice is for anyone who has upgraded to ODataLib v7, who may have implemented the previously accepted answers.
If you have the Microsoft.OData.Core nuget package v7 or later then this applies to you :). If you are still using older versions then use the code provided by @stas-natalenko but please DO NOT stop inheriting from ODataController... 

We can globally override the DefaultODataSerializer so that null values are omitted from all Entity and Complex value serialized outputs using the following steps:

Define your custom Serializer that will omit properties with null values

Inherit from Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSerializer

/// <summary>
/// OData Entity Serilizer that omits null properties from the response
/// </summary>
public class IngoreNullEntityPropertiesSerializer : ODataResourceSerializer
{
    public IngoreNullEntityPropertiesSerializer(ODataSerializerProvider provider)
        : base(provider) { }

    /// <summary>
    /// Only return properties that are not null
    /// </summary>
    /// <param name="structuralProperty">The EDM structural property being written.</param>
    /// <param name="resourceContext">The context for the entity instance being written.</param>
    /// <returns>The property be written by the serilizer, a null response will effectively skip this property.</returns>
    public override Microsoft.OData.ODataProperty CreateStructuralProperty(Microsoft.OData.Edm.IEdmStructuralProperty structuralProperty, ResourceContext resourceContext)
    {
        var property = base.CreateStructuralProperty(structuralProperty, resourceContext);
        return property.Value != null ? property : null;
    }
}

Define a Provider that will determine when to use our custom Serializer

Inherit from Microsoft.AspNet.OData.Formatter.Serialization.DefaultODataSerializerProvider

/// <summary>
/// Provider that selects the IngoreNullEntityPropertiesSerializer that omits null properties on resources from the response
/// </summary>
public class IngoreNullEntityPropertiesSerializerProvider : DefaultODataSerializerProvider
{
    private readonly IngoreNullEntityPropertiesSerializer _entityTypeSerializer;

    public IngoreNullEntityPropertiesSerializerProvider(IServiceProvider rootContainer)
        : base(rootContainer) {
        _entityTypeSerializer = new IngoreNullEntityPropertiesSerializer(this);
    }

    public override ODataEdmTypeSerializer GetEdmTypeSerializer(Microsoft.OData.Edm.IEdmTypeReference edmType)
    {
        // Support for Entity types AND Complex types
        if (edmType.Definition.TypeKind == EdmTypeKind.Entity || edmType.Definition.TypeKind == EdmTypeKind.Complex)
            return _entityTypeSerializer;
        else
            return base.GetEdmTypeSerializer(edmType);
    }
}

Now we need to Inject this into your Container Builder.

the specifics of this will vary depending on your version of .Net, for many older projects this will be where you are mapping the ODataServiceRoute, this will usually be located in your startup.cs or WebApiConfig.cs

builder => builder
    .AddService(ServiceLifetime.Singleton, sp => model)
    // Injected our custom serializer to override the current ODataSerializerProvider
    // .AddService<{Type of service to Override}>({service lifetime}, sp => {return your custom implementation})
    .AddService<Microsoft.AspNet.OData.Formatter.Serialization.ODataSerializerProvider>(ServiceLifetime.Singleton, sp => new IngoreNullEntityPropertiesSerializerProvider(sp));

And there you have it, re-exeecute your query and you should get the following:
{
 "odata.metadata":"http://localhost:28776/api/$metadata#Values",
 "value":[
   {
     "Id":1,
     "Name":"name1",
     "OptionalField":"Value Present"
   },
   {
     "Id":3,
     "Name":"name2"
   }
  ]
}

This is a very handy solution that can significantly reduce the data consumption on many data entry applications based on OData Services

NOTE: At this point in time, this technique must be used to override any of these default services: (as defined here OData.Net - Dependency Injection Support

Service                     Default Implementation      Lifetime    Prototype?
--------------------------  --------------------------  ----------  ---------
IJsonReaderFactory          DefaultJsonReaderFactory    Singleton   N
IJsonWriterFactory          DefaultJsonWriterFactory    Singleton   N
ODataMediaTypeResolver      ODataMediaTypeResolver      Singleton   N
ODataMessageReaderSettings  ODataMessageReaderSettings  Scoped      Y
ODataMessageWriterSettings  ODataMessageWriterSettings  Scoped      Y
ODataPayloadValueConverter  ODataPayloadValueConverter  Singleton   N
IEdmModel                   EdmCoreModel.Instance       Singleton   N
ODataUriResolver            ODataUriResolver            Singleton   N
UriPathParser               UriPathParser               Scoped      N
ODataSimplifiedOptions      ODataSimplifiedOptions      Scoped      Y

