7

I am working with my first Blazor app and running into a strange problem. I have a Web API that returns a fairly basic JSON response:

{
    "entityId": 26,
    "notifications": [
        {
            "type": "Success",
            "message": "The operation completed successfully."
        }
    ],
    "hasErrors": false,
    "hasWarnings": false
}

There is a standard POCO class that matches the above properties. From the Blazor app, when I try to get the response from an Http.PutAsJsonAsync<T>, an instance of the POCO class is created (so it's not null and doesn't throw an error), but none of the values above are actually present. The EntityId property is null and Notifications is instantiated but empty. The way I'm trying to access the response is:

var result = await Http.PutAsJsonAsync<ManufacturerModel>($"manufacturers", (ManufacturerModel)context.Model);
if (result.IsSuccessStatusCode)
{
  var response = await JsonSerializer.DeserializeAsync<EntityResponseModel>(result.Content.ReadAsStream());
    
  //response isn't null - it's just a newly created object with nothing mapped
}

Via the console in Chrome, I've confirmed the proper JSON is returned so it's really confusing why it'd create a new instance of that class, but not map any of the values.

Any ideas?

**** EDIT - including POCO definition ****

public class EntityResponseModel : BaseModel
{
    /// <summary>
    /// Gets or sets the Id of the affected entity
    /// </summary>
    public long? EntityId { get; set; }
}

public class BaseModel
{
    public BaseModel()
    {
        this.Notifications = new EntityNotificationCollection();
    }

    #region Validation

    /// <summary>
    /// Adds a notification to this model.
    /// </summary>
    /// <param name="type">The type of notification</param>
    /// <param name="message">The message to display</param>
    public void AddNotification(EntityNotificationTypes type, string message)
    {
        this.Notifications.Add(new EntityNotification { Type = type, Message = message });
    }

    /// <summary>
    /// Gets or sets the collection of notifications
    /// </summary>
    public EntityNotificationCollection Notifications { get; private set; }

    /// <summary>
    /// Gets whether errors exist on this model.
    /// </summary>
    //[JsonIgnore]
    public bool HasErrors { get => this.Notifications.HasErrors; }

    /// <summary>
    /// Gets whether warnings exist on this model
    /// </summary>
    //[JsonIgnore]
    public bool HasWarnings { get => this.Notifications.HasWarnings; }

    #endregion
}
Scott Salyer
  • 2,165
  • 7
  • 45
  • 82
  • Have you tried reading the stream as an Async stream? `var response = await JsonSerializer.DeserializeAsync(await result.Content.ReadAsStreamAsync());` – Kane Feb 09 '21 at 17:10
  • Just tried that (had a similar variant, but yours is more concise) and the exact same thing occurs. POCO instance is created, no errors generated, but it doesn't have any of the property values. – Scott Salyer Feb 09 '21 at 17:19
  • 2
    What is your POCO class definition, please [edit] question – Charlieface Feb 09 '21 at 17:22
  • @Charlieface done! – Scott Salyer Feb 09 '21 at 17:36
  • Yeah well, JsonSerializer is case-sensitive, so there is your answer. Exactly as I thought – Charlieface Feb 09 '21 at 17:37
  • 2
    Does this answer your question? [Json.NET Case-insensitive Property Deserialization](https://stackoverflow.com/questions/11266695/json-net-case-insensitive-property-deserialization) – Seeds Feb 09 '21 at 17:51
  • 1
    Sigh - it's been a week and it's a little embarassing something so obvious was the culprit. Using `PropertyNamingPolicy` via `JsonSerializerOptions` took care of it and now everything is happy. Thank you! – Scott Salyer Feb 09 '21 at 17:51

2 Answers2

9

You can specify your serialization settings and define it as being case sensitive or insensitive. CharlieFace provided this answer above.

Looks like you need to add your JsonAttribute to managing your case sensitivity.

var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true,
};
Seeds
  • 372
  • 2
  • 14
  • 1
    This solved it for me. Seems like there is an inconsistency in the default deserialization behavior for ```response.Content.ReadFromJsonAsync``` and ```JsonSerializer.DeserializeAsync```. – The Thirsty Ape Nov 19 '21 at 16:19
5

This is my full solution:

var retList = new List<PocoSomeClassData> (); 
var response = await client.GetAsync(uri); 
if (response.IsSuccessStatusCode) {
        using (var reponseStream = await response.Content.ReadAsStreamAsync())
        {
            var options = new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true,
            };
            retList = await JsonSerializer.DeserializeAsync < List<PocoSomeClassData> > (reponseStream,options);
        } 
}
AnthonyLambert
  • 8,768
  • 4
  • 37
  • 72