0

I'm trying to build micro service with TMDB API.

IApiClient

Code:

using System.Text.Json;
using Microsoft.Extensions.Options;
using Net5Micro.Config;
using RestSharp;

namespace Net5Micro.Services
{
    public class ApiClient : IApiClient
    {
        private readonly ServiceSettings _settings;
        
        public ApiClient(IOptions<ServiceSettings> settings)
        {
            _settings = settings.Value;
        }
        
        public Movie GetById(string id)
        {
            //Init rest client
            var client = new RestClient($"{_settings.TMDBhost}/movie/{id}");
            
            //Init rest request
            var request = new RestRequest(Method.GET);
            request.RequestFormat = DataFormat.Json;

            //Add Request params
            request.AddParameter("api_key", _settings.ApiKey, ParameterType.GetOrPost);

            //Calling Api 
            var response = client.Get(request);
            
            var movies = JsonSerializer.Deserialize<Movie>(response.Content);
            
            return movies;
        }

        // Za najpopularnije
        public Movies Discover(string sort)
        {
            //Init rest client
            var client = new RestClient($"{_settings.TMDBhost}/discover/movie/");
            
            //Init rest request
            var request = new RestRequest(Method.GET);
            request.RequestFormat = DataFormat.Json;
            
            //Add Request params
            request.AddParameter("api_key", _settings.ApiKey, ParameterType.GetOrPost);
            request.AddParameter("sort_by", sort, ParameterType.GetOrPost);
            
            //Calling Api 
            var response = client.Get(request);
            
            var movies = JsonSerializer.Deserialize<Movies>(response.Content);
            
            return movies;
        }
        
        public record Movie(int id, string original_title, string poster_path);
        public record Movies(int page, Movie[] results);
    }
}

Controller

GetById() works fine, but Discover() throws an error. On debugging I discovered the value returned is text/html instead of json; I think that's the problem.

response value

And here is the error

Exception has occurred: CLR/System.Text.Json.JsonException

An exception of type 'System.Text.Json.JsonException' occurred in System.Text.Json.dll but was not handled in user code: 'The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.'

Inner exceptions found, see $exception in variables window for more details.

Innermost exception
System.Text.Json.JsonReaderException : The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. LineNumber: 0 | BytePositionInLine: 0.

at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan1 bytes) at System.Text.Json.Utf8JsonReader.Read() at System.Text.Json.Serialization.JsonConverter1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state))

I'm new to .NET so I don't know how to fix it. Thanks in advance.

2 Answers 2

2

It returns a HTTP 301 Moved Permanently. Maybe you should follow that move response and access a different URL instead. Get it from the location header as defined in RFC2616.

Your code is missing error handling. It probably should process the response only in case of HTTP 200 OK. Parsing JSON from a HTTP 401 Forbidden does probably not make sense either.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot i followed URL and found a bit diffrent one that returns application/json.
0

There are a couple things that you can try ...

  1. Make sure the URL you're using is correct, e.g., remove trailing slash.
  2. Is the returned value really json for an object :Movies? OR is it a List<Movie>? i.e., { json of an object } vs. [ json of a list of objects ]
  3. You want the 'Accept' header to be 'application/json' not the content type, but since your GET example works, I really think it's #1 or #2.

Try this:

        public Movies Discover(string sort)
        {
            //Init rest client
            var client = new RestClient($"{_settings.TMDBhost}/discover/movie"); // no trailing slash
            
            //Init rest request
            var request = new RestRequest(Method.GET);
            //request.RequestFormat = DataFormat.Json; // not required
            
            //Add Request params
            request.AddParameter("api_key", _settings.ApiKey, ParameterType.GetOrPost);
            request.AddParameter("sort_by", sort, ParameterType.GetOrPost);
            
            //Calling Api - can deserialize directly to your Movies var.
            var movies = client.GetAsync<Movies>(request).Result;
            // #2 - might be a list that you get back? if so .. something like this:
            // var mlist = client.GetAsync<List<Movie>>(request).Result;
            // var movies = new Movies(); // add your mlist as needed to movies.                        
            return movies;
        }

You can also try testing the .../movie endpoint in Postman to see what is actually returned.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.