Building a Gateway to Netflix API: A Developer's Guide
Tags: programming, api, csharp, tutorial
Published: 2023-11-20 09:36:47

## Introduction: Creating in C# .NET Netflix API Gateway

In this article, we embark on an exciting journey to create a C# API client that interfaces with the [Netflix API](https://rapidapi.com/dataocean/api/netflix99). It's important to note that Netflix doesn't offer an official API, so we'll be utilizing a set from RapidAPI. Among the options, DataOcean's [Netflix API](https://rapidapi.com/dataocean/api/netflix99) emerged as my top pick for several compelling reasons:
- Its novelty often translates to better features.
- The simplicity is key — with just 7 endpoints, it covers nearly all desired functionalities.
- Affordability is a great plus.
- Rapid performance seals the deal.

With these criteria in mind, let's dive in!

## Setting Up Our Project in Visual Studio

First things first, we'll adhere to a naming convention for clarity and organization: `ApiHarbor.RapidApi.Author.ApiName`.

![The screenshot showcasing the initial setup in Visual Studio, emphasizing the selection of .NET Standard 2.0](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/afm5acxhghdbucy1k1p6.png)

Our project's initial layout looks fantastic and promising. The guiding principle here is "less code, more efficiency." At this point, our codebase is a clean slate, perfectly set up for our next steps 😉.
![Configure project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jn4u5lftbqww44elsvnf.png)
Now, let's break this perfection by adding the code 😉.

## Crafting the NetflixApiClient.cs: Connecting to Netflix API

To query an endpoint on RapidApi, two additional header values are crucial:
- `X-RapidAPI-Key`
- `X-RapidAPI-Host`

You can find these in the Code Snippets section on the API's webpage - https://rapidapi.com/dataocean/api/netflix99

![The screenshot illustrating where to find these values on the website.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vpual7c2zfz1x9baiwpd.png)

Our `NetflixApiClient` constructor should definitely accept a `rapidApiKey` for use in requests. Let's consider if we need anything else. For sure something that communicates over `http/s`. In C#, there are several methods for this, we can use:
- [WebClient](https://learn.microsoft.com/en-US/dotnet/api/system.net.webclient?view=netstandard-2.0)
- [WebRequest](https://learn.microsoft.com/en-us/dotnet/api/system.net.webrequest?view=netstandard-2.0) and [WebResponse](https://learn.microsoft.com/en-us/dotnet/api/system.net.webresponse?view=netstandard-2.0)
- [HttpClient](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netstandard-2.0)
- [RestSharp](https://restsharp.dev/)
- [Flurl](https://flurl.dev/)
and others

We wouldn't want to restrict the user to a specific method, so our constructor will accept an `IWebClient` interface. This way, users can choose their preferred implementation. A logger would also be handy to know what's happening during API usage. We'll follow a similar approach as before, providing a custom `ILogger` interface, compelling the user to implement it.

## Implementing IWebClient

`IWebClient` should be straightforward, with a single method to retrieve content from a given URL and the ability to add headers to the request.
![A screenshot show a simple interface design for IWebClient.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4nms77dnuouwzjmepq85.png)

## Implementing ILogger

Here, we aim for simplicity. Our logger should have two methods: one for informational messages and another for handling exceptions.

![The screenshot showing the basic structure of the ILogger interface.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/daavad6bnsaczb2zhz59.png)

Returning to our `NetflixApiClient.cs`, let's implement what we've outlined so far.

![The screenshot of the initial NetflixApiClient implementation.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z31jx8o8et3ymiw6o0s4.png)

With the current implementation, we meet all our initial objectives:
- Flexibility in passing any `http/s` communication implementation.
- Freedom from being tied to any particular logger implementation.
- The constructor accepts our `X-RapidAPI-Key`.

Let's move on to the more exciting parts! 🔥

## Implementing Netflix API Methods

The [Netflix API](https://rapidapi.com/dataocean/api/netflix99) we're working with provides seven endpoints:
- **Search titles** - title search (surprise! 😃)
- **Title lists** - returns titles according to defined parameters
- **Title details** - returns title details based on the ID from Search title
- **Similar titles** - returns similar titles also with ID received from Search
- **Title credits** - returns a list of actors and people working on the title
- **Title media** - returns a listing of images, posters, videos
- **Person details** - retrieves information about a given actor or team member. Accepts ID received from Title credits.

As our first method to implement, let's choose `Search title`, as the other endpoints require IDs returned by this method.

## Netflix API: Search titles and Implementation

The `Search` titles endpoint accepts several parameters, including:
- `query` - searched phrase
- `order` - sorting of results
- `title type` -  option to return results only for movies or TV shows or all (All)
- `country`
- `language`
- `release year` (from/to)
- `rating` (min/max)
- `token` - for the next page of results

Let's make a sample request and examine the response from `Search titles`.

![The screenshot of the request and response structure.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d0ecs87uvejic3zl2c0j.png)

**Key Observations:**
- Status information is provided (e.g., `status: 200` for success).
- Relevant data is assigned to data.
- Separate pagination property includes a prepared URL for the next page and `next_page_token`.
- The total number of results and pages, as well as the number of titles returned per response, are provided.

Inspecting a single title element reveals:

![List key details about the title element.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ng5kww6n2nt09splaqot.png)

This gives us a good understanding of `Search titles`. Let's get to the implementation.

## Mapping the Response

We'll create a new class to map the JSON response from the API to a `SearchTitlesResponse` object. In today's world, manual JSON mapping is a thing of the past. Tools like [json2csharp](https://json2csharp.com/) make this task a breeze. Let's use it to generate our response class.

Copy the entire JSON and then paste it into [json2csharp ](https://json2csharp.com/) and click on Convert.

![The process of using [json2csharp](https://json2csharp.com/).](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1w0ekkql1gthn7n3ral6.png)

A beautiful response class has been generated for us. We will further enhance it by adding **nullable **fields and using **PascalCase**

![Recommended settings.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ovbhqhndnzwanzs41muo.png)

Now it's perfect! Just take a look at the response.

![Response generated by json2csharp.com](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d3ohhpbobuc39d634fga.png)

Our class is ready, let's integrate it into our project.

As we see something is missing. To use `JsonProperty`, we need to install `Newtonsoft.Json`.

![Installing Newtonsoft.Json](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rie787cfaqx7epzmp4yi.png)

And by the way, we will implement a static method that will convert (deserialize) pure JSON in text form into a `SearchTitlesResponse.Root` object.

![Json deserialization to SearchTitleResponse.Root](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ohvn4f9mu31t3leu2j95.png)

The structure of our project currently looks like:

![Structure of the project.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9tszc97mgrd6c31whziq.png)
Great! Now that we can map the JSON to `SearchTitlesResponse`, it's time to fetch the JSON from the [Netflix API](https://rapidapi.com/dataocean/api/netflix99).

Let's go to `NetflixApiClient` and implement the method.

![Implementing SearchTitles metod in NetflixApiClient class.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yu1gua9xl80ns70xlun7.png)

Remember, Search titles can accept numerous parameters, so let's get those implemented.

![The implementation of the parameters of SearchTitles method.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/efn8eejv642osxds7j7f.png)

Quite a long process. Well, let's move on…

![Too long process.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3h9eh87d57e9ilv9tvpf.png)

However let's STOP here! Instead of building a raw URL string in the client, let's create a separate `SearchTitlesRequest` class that handles query parameters and returns a formatted URL for communication with the [Netflix API](https://rapidapi.com/dataocean/api/netflix99).

![Implementation of SearchTitlesRequest.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/738lj0ulenflge2g1659.png)

Let's add another method that will return joined parameters for us.

![ToQueryParams metod.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/alf24075d6zc1o6uhmpn.png)

Yes. In this way, I avoid writing long strings, I prefer to put each parameter separately into an array and then join them with &. It looks better, right? 😃 Let's look at the full implementation of SearchTitles.


![The complete implementation of SearchTitles methods.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/isuxxuihix07uy305hcl.png)


We can call the `SearchTitles` method by passing a `SearchTitlesRequest` object or using ordinary parameters.

Now the handling of the Search title endpoint looks awesome!🔥

## Making IWebClient and ILogger Optional for the User (Dependency Injection)

Before testing our Search method, let's modify one assumption. We gave users the option to implement their own `http/s` communication and logger. But not everyone might want to do this. Some might prefer a straightforward way to fetch data without extra implementation. Let's accommodate this preference.

## Implementing Default WebClient

We add a new `DefaultWebClient` class in `Infrastructure.Implementations`, using `HttpClient` for requests.


![The implementation of DefaultWebClient.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x84gxey52bzgf5t8jzf5.png)

## Implementing Default Logger

Similarly, we add a `DefaultLogger` class in the same namespace, providing the simplest implementation of the `ILogger` interface.


![The implementation of DefaultLogger.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fmlzg3ovusz04rarfjdh.png)

The default logger will simply display messages in the Console. Users can always implement their own logger for different outputs, like file logging or database storage.

## Modifying NetflixApiClient Constructor

Since we're not enforcing the use of custom `IWebClient` or `ILogger`, we need to adjust the constructors of `NetflixApiClient`.

![The new constructors providing more flexibility to the user.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k6dwpcghx5uejiki1t4v.png)

With these new constructors, users now have the choice to use the defaults or implement their own!

## Testing Search Titles

To test the [Netflix API](https://rapidapi.com/dataocean/api/netflix99), all we need is the `X-RapidAPI-Key` and some code.

![The test setup and results.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fynwz4vtu5s7bkz7mh3r.png)
Running the console application…

![The Big Test!](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0n84rbopnxnai3ytk105.png)
… yields our results. 🔥 Everything works as expected. Great job 🤝

Let's also test fetching subsequent pages of results using the provided URL.

We need to modify `NetflixApiClient` to add a simple variant of the `SearchTitles` method, named `SearchTitlesByUrl`, accepting the `next_page_url`.

![The modification of SearchTitle.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2kkeeoy3a0gzznf3vk8g.png)

Let's modify the test code a bit more in the console application. The modification concerns querying the next page (we have it at hand in `NextPageUrl`). The querying loop will operate until Data is not empty. Simple and effective 👌

![Testing code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k7bf3b4wo3vdz5rfh6ry.png)

Running the code with modification from above…

![The successful test results.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qrfsehvy6whddngd1gix.png)

…gives us correct results. We can observe this through the titles come from the next (second) page. Brilliant!

What's next? I believe it's time to tackle the `Title details` endpoint.


## What's next?

I believe it's time to tackle the Title details endpoint.

## Netflix API: Title Details and Implementation

From the [RapidApi documentation](https://rapidapi.com/dataocean/api/netflix99) for [Netflix API](https://rapidapi.com/dataocean/api/netflix99), we know that the Title details endpoint requires an id parameter.

![The Title Details id param documentation.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3iu6nby3t128v0d7w1x3.png)
As we remember, we can find the id in `Search title` and `List titles`. Alright, let's start with mapping the response from Title details. We will use the knowledge we have already acquired!

- Visit the [Netflix API](https://rapidapi.com/dataocean/api/netflix99) page on RapidApi.
- Choose the `Title details` endpoint and execute it.
- Copy the JSON result.
![Copying the JSON result from the API endpoint.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/abc9sj1qr6iyiuuxlo8o.png)
- Use [json2csharp ](https://json2csharp.com/) to generate the `TitleDetailsResponse` class.
- Remember to set Property Settings as follow
![json2csharp property settings.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aw2cpbeh7920tbzbuyg1.png)
- We paste the JSON and click 'Convert' button.
- We create a new class in Responses: `TitleDetailsResponse` and implement the Create method (as before).

![The implementation of TitleDetailsResponse.Create method.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fcoqo0qnpfuex3tkfgbs.png)
- Let's see how it looks now

![TitleDatailsResponse](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rz71ohr2zt711qi25p3c.png)
- JSON to response object mapping seems to be ready!

Now let's implement the API request method in our `NetflixApiClient`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ygp1gjbhdrdqzpec8w63.png)

Yes, this simple code is sufficient. This time, we won't implement the creation of the API URL in the response class (`TitleDetailsResponse`), as the needed URL is very simple. But of course, following good practices, we should do so… Anyways! We need the test code to check if getting `TitleDetails` works.

![Testing the NetflixApiClient.TitleDetails method.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8kd73jhrcosnzzy5qer1.png)

![The result of testing TitleDetails method.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8vywq09t08x6d9xuy5j9.png)
And there you have it, a quick and efficient implementation! 😊

## Conclusion

Today, we nearly completed an entire library for interacting with the [Netflix API](https://rapidapi.com/dataocean/api/netflix99).

- We added default classes for `http/s` communication with API and a console-based logger.
- By using Dependency Injection, we provided the option for users to create their own versions of an HTTP client and logger through our interfaces `IWebClient` and `ILogger`.
- Responses are neatly mapped from raw JSON text to Response objects with the help of the [json2csharp.com](https://json2csharp.com/)
- And the most important result of the project: we are able to very easily retrieve data from the API using our client class - `NetflixApiClient`.

Everything went smoothly and easily… perhaps even too easily 😉
You can check out the entire project on GitHub:
https://github.com/apiharbor/ApiHarbor.RapidApi.DataOcean.NetflixApi

Next time, we'll build a sample project using this library… OR! we'll write another article expanding the library with some additional interesting features. We'll see.

Thanks for your time ❤️ See you!
Follow me to not miss out on future updates! 🔥