InvalidOperationException: Cannot get the value of a token type 'Number' as a string
Asked Answered
C

2

11

Full Error: InvalidOperationException: Cannot get the value of a token type 'Number' as a string. System.Text.Json.Utf8JsonReader.GetString()

JsonException: The JSON value could not be converted to System.String. Path: $[0].status | LineNumber: 0 | BytePositionInLine: 197. System.Text.Json.ThrowHelper.ReThrowWithPath(ref ReadStack state, ref Utf8JsonReader reader, Exception ex)

I have MVC project that is trying consume Web API that is working correctly. Now, there is HouseController.cs

using Microsoft.AspNetCore.Mvc;
using Task3.Controllers.Services;
 
namespace Task3.Controllers;
 
public class HouseController : Controller
{
    private readonly IHouseService _service;
 
    public HouseController(IHouseService service)
    {
        _service = service ?? throw new ArgumentNullException(nameof(service));
    }
 
    public async Task<IActionResult> Index()
    {
        var houses = await _service.Find();
        return View(houses);
    }
}

that is calling Find() method in interface IHouseService

using Task3.Models;
 
namespace Task3.Controllers.Services
{
    public interface IHouseService
    {
        Task<IEnumerable<HouseModel>> Find();
    }
}

that in its turn calls the same method in HouseService.cs

using Task3.Controllers.Helper;
using Task3.Models;
 
namespace Task3.Controllers.Services
{
    public class HouseService : IHouseService
    {
        private readonly HttpClient _client;
        public const string BasePath = "/api/Houses";
 
        public HouseService(HttpClient client)
        {
            _client = client ?? throw new ArgumentNullException(nameof(client));
        }
 
        public async Task<IEnumerable<HouseModel>> Find()
        {
            var response = await _client.GetAsync(BasePath);
 
            return await response.ReadContentAsync<List<HouseModel>>();
        }
    }
}

which calls ReadContentAsync<List<HouseModel>>()

using Newtonsoft.Json;
using JsonSerializer = System.Text.Json.JsonSerializer;
 
namespace Task3.Controllers.Helper
{
    public static class HttpClientExtensions
    {
        public static async Task<T> ReadContentAsync<T>(this HttpResponseMessage response)
        {
            if (response.IsSuccessStatusCode == false)
                throw new ApplicationException($"Something went wrong calling the API: {response.ReasonPhrase}");
 
            var dataAsString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
 
            Console.WriteLine(dataAsString);
 
            var result = JsonSerializer.Deserialize<T>(dataAsString);
 
            return result;
        }
    }
}

and the line with Deserialize<T> returns the before mentioned error.

What I tried is obviously debugging, the Deserialize<T> method, besides returning error, returns null 'cause it apparently cannot convert Json result to Model attributes. Here is HouseModel

namespace Task3.Models;
 
public class HouseModel
{
    public string Price { get; set; }
    public string Region { get; set; }
    public string PublicationDate { get; set; }
    public string GeoLat { get; set; }
    public string GeoLon { get; set; }
    public string BuildingType { get; set; }
    public string Area { get; set; }
    public string Rooms { get; set; }
    public string FloorNum { get; set; }
    public string TotalFloor { get; set; }
    public string ObjectType { get; set; }
    public string Id { get; set; }
    public string status { get; set; }
    public string Photo { get; set; }
}

Btw, before that HouseModel attributes were int, DateTime etc. and the error was cannot convert to Int32.

Also I used custom Converter StringConverter

public class StringConverter : System.Text.Json.Serialization.JsonConverter<string>
        {
            public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
            {
 
                if (reader.TokenType == JsonTokenType.Number)
                {
                    var stringValue = reader.GetInt32();
                    stringValue = stringValue;
                    return stringValue.ToString();
                }
                else if (reader.TokenType == JsonTokenType.String)
                {
                    return reader.GetString();
                }
 
                throw new System.Text.Json.JsonException();
            }
 
            public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
            {
                writer.WriteStringValue(value);
            }
 
        }

but in that case every entry is null.

Can anybody share some insight?

Catharina answered 13/11, 2022 at 21:35 Comment(0)
C
4

I solved the problem myself. The problem was that I was using two different models. One in MVC and the one in API, they had different datatypes and variable names which was the main problem.

Catharina answered 16/11, 2022 at 6:57 Comment(0)
R
0

It is important to make sure that the value from the Json have the same Datatype with the properties of the class.

public string CityName { get; set; }

json = "{\"CityName\":\"Bafoussam\"}"
Romie answered 10/5, 2023 at 22:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.