.Net 6 - Unable to use Newtonsoft as default JSON serializer

Sebastian,

I had to port my .net 5 react spa over to .net 6 due to some architecture requirements. I can’t seem to do services.AddMvc().AddNewtonsoftJson(); like I used to in .net 5. Most of my proxy Web API controllers are returning JSON properly, however I am seeing one controller endpoint (a YouTube Proxy) return JSON with a bunch of empty arrays. I think this is because if a Serialization error from System.Text.Json. I’m aware of some of the issues here, but was wondering off hand if you had any suggestions for migrating to .net 6 since Newtonsoft is necessary.

API Client:

public async Task<dynamic> GetYouTubeVideos(string YouTubeApiKey, string PlaylistId, int Limit)
        {
            using (var client = new HttpClient())
            {
                var url = string.Format($"https://youtube.googleapis.com/youtube/v3/playlistItems?key={YouTubeApiKey}&playlistId={PlaylistId}&part=snippet,id&maxResults={Limit}");

                try
                {
                    var req = new HttpRequestMessage(HttpMethod.Get, url);

                    var result = client.SendAsync(req).Result;
                    result.EnsureSuccessStatusCode();

                    var ytRes = await result.Content.ReadAsStringAsync();

                    var output = JsonConvert.DeserializeObject<dynamic>(ytRes);

                    return output;
                }
                catch (Exception ex)
                {
                    return new { ErrorMessage = ex.Message };
                }
            }

            return new { ErrorMessage = "No result from YT API" };
        }

API Controller

[HttpGet]
[Route("YouTubePlaylist/{PlaylistId}/{Count}")]
        public async Task<JsonResult> GetPlaylistVideos(string PlaylistId, int Count)
        {
            var cacheKey = string.Concat(CacheKeys.Videos.ToString(), ".", PlaylistId, ".", Count);

            //Check cache
            if (_cacheEnabled)
            {
                var videos = string.Empty;
                _memoryCache.TryGetValue<string>(cacheKey, out videos);
                if (!string.IsNullOrEmpty(videos))
                {
                    //return cached version
                    var videosFromCache = JsonSerializer.Deserialize<dynamic>(videos);
                    return new JsonResult(videosFromCache);
                }
            }

            //Not cached, cache it!
            var apiKey = _config.GetValue<string>("YouTube.APIKey");
            var videosResult = await _apiClient.GetYouTubeVideos(apiKey, PlaylistId, Count < 50 ? Count : 50);
            _utilities.SetCache(cacheKey, JsonSerializer.Serialize(videosResult));

            return new JsonResult(videosResult);
        }

I think this question has nothing to do with Squidex, but I will answer it anyway.

services.AddMvc().AddNewtonsoftJson();

This will work for 100%, because I have used it as well before the migration.

var ytRes = await result.Content.ReadAsStringAsync();

var output = JsonConvert.DeserializeObject(ytRes);

The problem is the dynamic aspect here. Dynamic is probably not compatible with SystemTextJson and I am not sure what Newtonsoft even generates. Perhaps JToken.

So you have to use an object that is compatible with SystemTextJson. I woul use JsonDocument and this method: https://docs.microsoft.com/en-us/dotnet/api/system.text.json.jsondocument.parse?view=net-6.0#system-text-json-jsondocument-parse(system-io-stream-system-text-json-jsondocumentoptions)

You can also read from style directly and avoid the buffering into a string, which is not only faster, but also consumes less memory.