OData / OData/AspNetCoreOData

Empty json result when $select over PhysicalAddress

Open
#1,002 5 comments 1 reaction 1 assignee View on GitHub

@xuzhg is already working on this.

Since Aug 1, 2023.

followup investigated wontfix
Dominant language
C#
Stars
505
Forks
186
PR merge metrics
No merged PRs in 30d

Description

Assemblies affected
ASP.NET Core OData 8.2

Describe the bug
When trying to $select a field which is a System.Net.NetworkInformation.PhysicalAddress, the result is empty.

Reproduce steps

  • Modify the ODataNewtonsoftJsonSample code to add a PhysicalAddress to the model.
    Data Model

    model

  • Add a converter for System.Net.NetworkInformation.PhysicalAddress

// <copyright file="MACConverter.cs">

namespace ODataNewtonsoftJsonSample
{
    using System;
    using System.Net.NetworkInformation;
    using Newtonsoft.Json;

    /// <summary>
    /// Mac converter.
    /// </summary>
    public class MACConverter : JsonConverter<PhysicalAddress>
    {
        /// <summary>
        /// Read JSON.
        /// </summary>
        /// <param name="reader">Json reader.</param>
        /// <param name="objectType">Object type.</param>
        /// <param name="existingValue">existing value to read.</param>
        /// <param name="hasExistingValue">If has existing value to read.</param>
        /// <param name="serializer">Json serializer.</param>
        /// <returns>Element readed.</returns>
        public override PhysicalAddress ReadJson(JsonReader reader, Type objectType, PhysicalAddress existingValue, bool hasExistingValue, JsonSerializer serializer)
        {
            var value = reader.Value;

            if (value is null)
            {
                return null;
            }

            try
            {
                // If value is not a string, an exception will be thrown.
                string macValue = (string)value;

                return CreatePhysicalAddressFromMAC(macValue);
            }
            catch (Exception exception)
            {
                throw new FormatException(exception.Message);
            }
        }

        /// <summary>
        /// Write JSON.
        /// </summary>
        /// <param name="writer">Json writer.</param>
        /// <param name="value">value to convert.</param>
        /// <param name="serializer">Json serializer.</param>
        public override void WriteJson(JsonWriter writer, PhysicalAddress value, JsonSerializer serializer)
        {
            writer.WriteValue(value.ToString());
        }

        public static PhysicalAddress CreatePhysicalAddressFromMAC(string mac)
        {
            if (mac is null)
            {
                return null;
            }

            try
            {
                // If value is empty, an exception will be thrown.
                if (string.IsNullOrEmpty(mac))
                {
                    throw new FormatException("An invalid physical address was specified: ''");
                }

                return PhysicalAddress.Parse(mac);
            }
            catch (Exception exception)
            {
                throw new FormatException(exception.Message);
            }
        }
    }
}

  • Modify the Startup.cs to add the converter
public void ConfigureServices(IServiceCollection services)
        {
            var converters = new List<JsonConverter>
            {
                new MACConverter(),
            };


            services.AddControllers()
                .AddOData(opt => opt.Select().Filter().Count().SetMaxTop(10).AddRouteComponents("odata", GetEdmModel()))
                .AddNewtonsoftJson(
                options =>
                {
                    options.SerializerSettings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore;
                    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
                    //options.SerializerSettings.ContractResolver = WebApiJsonResolver.Instance;
                    options.SerializerSettings.Converters = converters;
                })
                .AddODataNewtonsoftJson()
                ;
        }
  • Modify the WeatherForecastController to add a value for the new field
        [HttpGet]
        [EnableQuery]
        public IEnumerable<WeatherForecast> Get()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)],
                Mac = PhysicalAddress.Parse("00:0E:59:00:00:00"),
            })
            .ToArray();
        }
  • Try to $select the new field.
  • The result is empty.

EDM (CSDL) Model
model2

Request/Response
The new field is correctly parsed without selecting it
requestWithoutSelect

The $select does not know how to parse the new field and the response is empty.
requestWitSelect

Expected behavior
When trying to $select a field which is a System.Net.NetworkInformation.PhysicalAddress, the result is correctly.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.