2
votes

I am developing a .Net Core 2.2 Web API. I am attempting to take advantage of ControllerBase methods such as AcceptedAtAction, Ok, etc. I have configured my JsonSerializerSettings via .AddJsonOptions in my Startup.cs. However, these action methods appear to ignore the serialization settings. Is there something else I need to do in order to have these methods honor these settings?

Startup.cs

.AddJsonOptions(opts =>
  {
    opts.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Ignore;
    opts.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
    opts.SerializerSettings.ContractResolver = new EmptyCollectionContractResolver();
  })

Controller

return AcceptedAtAction(
    nameof(GetPayEntryImport),
    new
    {
      companyId = companyId,
      id = timeImportResponseModel.TimeImportFileTrackingId,
      version = apiVersion.ToString()
    },
    timeImportResponseModel);

Response with empty collections serialized as empty arrays which shouldn't be the case given the ContractResolver I am utilizing.

{
    "timeImportFileTrackingId": "bd3cd9fc-09c7-4da0-b1d9-eb8863841ed8",
    "status": "The file was accepted and is currently being processed.",
    "postProcessingResults": [],
    "processedData": []
}

EmptyCollectionContractResolver

public class EmptyCollectionContractResolver : CamelCasePropertyNamesContractResolver
  {
    protected virtual JsonProperty CreateProperty(
      MemberInfo member,
      MemberSerialization memberSerialization)
    {
      JsonProperty property = base.CreateProperty(member, memberSerialization);
      Predicate<object> shouldSerialize = property.get_ShouldSerialize();
      property.set_ShouldSerialize((Predicate<object>) (obj =>
      {
        if (shouldSerialize == null || shouldSerialize(obj))
          return !this.IsEmptyCollection(property, obj);
        return false;
      }));
      return property;
    }

    private bool IsEmptyCollection(JsonProperty property, object target)
    {
      object obj = property.ValueProvider.GetValue(target);
      switch (obj)
      {
        case ICollection collection:
          if (collection.Count == 0)
            return true;
          break;
        case null:
          return false;
      }
      if (!typeof (IEnumerable).IsAssignableFrom(property.get_PropertyType()))
        return false;
      PropertyInfo property1 = property.get_PropertyType().GetProperty("Count");
      if (property1 == (PropertyInfo) null)
        return false;
      return (int) property1.GetValue(obj, (object[]) null) == 0;
    }
  }
1
Please share some more details..it is hard to figure out What is missing with these statements...Atmanirbhar Bharat
Not sure the additional detail will help all that much. It's pretty cut and dry...the action methods appear to ignore those settings. I've encountered this before and I had to abandon using them but thought I'd see whether someone else encountered this and was a able to identify a resolution.chad
Where's the source for EmptyCollectionContractResolver? That might be at fault here, because the configuration you've applied should apply to AcceptedAtAction et al.Kirk Larkin
Where does EmptyCollectionContractResolver come from? I can only find one reference to it on google on some random guys GitHub.DetectivePikachu
The EmptyCollectionContractResolver works when I use JsonConvert.SerializeObject and supply serialization settings.chad

1 Answers

1
votes

This issue was caused by our configuration of an OutputFormatter in the AddMvc extension method. If you haven't configured any JsonOutputFormatters, you should be fine and AddJsonOptions will provide what you need. Otherwise, ensure the serialization settings you want are configured for the JsonOutputFormatter.