Implementing TheMovieDB (TMDB) API in ASP.NET MVC

Implementing TheMovieDB (TMDB) API in ASP.NET MVC

Introduction to TheMovieDB API

The Movie Database (TMDb) is a community built movie and TV database. Every piece of data has been added dating back to 2008. TMDb’s strong international focus and breadth of data is largely unmatched and available through the mean of TheMovieDb API. You can use this API to create different sort of features like searching movie, actors, TV series, companies, reviews and much more.

In this tutorial I will implement TMDB API where users can search any actor by name and get their complete details. I will implement this in ASP.NET MVC application.

Generate you API Key

First you need to create your account in the TMDB Website then go to the Settings >API to generate your API key.

More information is given here.

What It should Look

I will create 2 views – in the first view user can search actors by their names.

TheMovieDB actor result

In the second view the information of an actor is shown.

TheMovieDB tom cruise result

Note – On clicking the image of an actor shown on the first view the second view will open.

Create TheMovieDb Model

Let’s move to the implementation part of TheMovieDb API.

Add a new class to the Models folder and name it TheMovieDb add the following properties to it.

public class TheMovieDb
{
    [Required]
    public string searchText { get; set; }
    public bool adult { get; set; }
    public string also_known_as { get; set; }
    public string biography { get; set; }
    public string birthday { get; set; }
    public string deathday { get; set; }
    public int gender { get; set; }
    public string homepage { get; set; }
    public int id { get; set; }
    public string imdb_id { get; set; }
    public string name { get; set; }
    public string place_of_birth { get; set; }
    public double popularity { get; set; }
    public string profile_path { get; set; }
}

Create Some Helper Classes

I will need some Helper classes to serialize the JSON and creating the paging links. Create these classes inside a new Class folder.

These classes are:

public class KnownFor
{
    public string poster_path { get; set; }
    public bool adult { get; set; }
    public string overview { get; set; }
    public string release_date { get; set; }
    public string original_title { get; set; }
    public List<object> genre_ids { get; set; }
    public int id { get; set; }
    public string media_type { get; set; }
    public string original_language { get; set; }
    public string title { get; set; }
    public string backdrop_path { get; set; }
    public double popularity { get; set; }
    public int vote_count { get; set; }
    public bool video { get; set; }
    public double vote_average { get; set; }
    public string first_air_date { get; set; }
    public List<string> origin_country { get; set; }
    public string name { get; set; }
    public string original_name { get; set; }
}

public class Result
{
    public string profile_path { get; set; }
    public bool adult { get; set; }
    public int id { get; set; }
    public List<KnownFor> known_for { get; set; }
    public string name { get; set; }
    public double popularity { get; set; }
}

public class ResponseSearchPeople
{
    public int page { get; set; }
    public List<Result> results { get; set; }
    public int total_results { get; set; }
    public int total_pages { get; set; }
}

public class ResponsePerson
{
    public bool adult { get; set; }
    public List<string> also_known_as { get; set; }
    public string biography { get; set; }
    public string birthday { get; set; }
    public string deathday { get; set; }
    public int gender { get; set; }
    public string homepage { get; set; }
    public int id { get; set; }
    public string imdb_id { get; set; }
    public string name { get; set; }
    public string place_of_birth { get; set; }
    public double popularity { get; set; }
    public string profile_path { get; set; }
}
public class PagingInfo
{
    public int TotalItems { get; set; }
    public int ItemsPerPage { get; set; }
    public int CurrentPage { get; set; }
    public int TotalPages
    {
        get
        {
            return (int)Math.Ceiling((decimal)TotalItems /
                ItemsPerPage);
        }
    }
}
public static class PagingHelper
{
    public static MvcHtmlString PageLinks(this HtmlHelper html, PagingInfo pagingInfo, Func<int, string> pageUrl)
    {
        StringBuilder result = new StringBuilder();
        string anchorInnerHtml = "";
        for (int i = 1; i <= pagingInfo.TotalPages; i++)
        {
            TagBuilder tag = new TagBuilder("a");
            anchorInnerHtml = AnchorInnerHtml(i, pagingInfo);

            if (anchorInnerHtml == "..")
                tag.MergeAttribute("href", "#");
            else
                tag.MergeAttribute("href", pageUrl(i));
            tag.InnerHtml = anchorInnerHtml;
            if (i == pagingInfo.CurrentPage)
            {
                tag.AddCssClass("active");
            }
            tag.AddCssClass("paging");
            if (anchorInnerHtml != "")
                result.Append(tag.ToString());
        }
            return MvcHtmlString.Create(result.ToString());
    }
    
    public static string AnchorInnerHtml(int i, PagingInfo pagingInfo)
    {
        string anchorInnerHtml = "";
        if (pagingInfo.TotalPages <= 10)
            anchorInnerHtml = i.ToString();
        else
        {
            if (pagingInfo.CurrentPage <= 5)
            {
                if ((i <= 8) || (i == pagingInfo.TotalPages))
                    anchorInnerHtml = i.ToString();
                else if (i == pagingInfo.TotalPages - 1)
                    anchorInnerHtml = "..";
            }
            else if ((pagingInfo.CurrentPage > 5) && (pagingInfo.TotalPages - pagingInfo.CurrentPage >= 5))
            {
                if ((i == 1) || (i == pagingInfo.TotalPages) || ((pagingInfo.CurrentPage - i >= -3) && (pagingInfo.CurrentPage - i <= 3)))
                    anchorInnerHtml = i.ToString();
                else if ((i == pagingInfo.CurrentPage - 4) || (i == pagingInfo.CurrentPage + 4))
                    anchorInnerHtml = "..";
            }
            else if (pagingInfo.TotalPages - pagingInfo.CurrentPage < 5)
            {
                if ((i == 1) || (pagingInfo.TotalPages - i <= 7))
                    anchorInnerHtml = i.ToString();
                else if (pagingInfo.TotalPages - i == 8)
                    anchorInnerHtml = "..";
            }
        }
        return anchorInnerHtml;
    }
}
To serialize JSON you have to create classes based on JSON format returned by the TheMovieDb API. This task is good time consuming work. I tell you to use json2csharp to make these classes based on your JSON format. It saves your valuable time.

Create TMDB Controller

Create a new Controller and name it TmdbApi and add the following Namespaces to it:

using System.Net;
using System.IO;
using Newtonsoft.Json;
using demo.MVC.Class;
using System.Text;

Now add the below code to it:

// GET
public ActionResult Index(string peopleName, int? page)
{
    if (page != null)
        CallAPI(peopleName, Convert.ToInt32(page));

    Models.TheMovieDb theMovieDb = new Models.TheMovieDb();
    theMovieDb.searchText = peopleName;
    return View(theMovieDb);
}
[HttpPost]
public ActionResult Index(Models.TheMovieDb theMovieDb, string searchText)
{
    if (ModelState.IsValid)
    {
        CallAPI(searchText, 0);
    }
    return View(theMovieDb);
}
public void CallAPI(string searchText, int page)
{
    int pageNo = Convert.ToInt32(page) == 0 ? 1 : Convert.ToInt32(page);

    /*Calling API https://developers.themoviedb.org/3/search/search-people */
    string apiKey = "3356865d41894a2fa9bfa84b2b5f59bb";
    HttpWebRequest apiRequest = WebRequest.Create("https://api.themoviedb.org/3/search/person?api_key=" + apiKey + "&language=en-US&query=" + searchText + "&page=" + pageNo + "&include_adult=false") as HttpWebRequest;

    string apiResponse = "";
    using (HttpWebResponse response = apiRequest.GetResponse() as HttpWebResponse)
    {
        StreamReader reader = new StreamReader(response.GetResponseStream());
        apiResponse = reader.ReadToEnd();
    }
    /*End*/

    /*http://json2csharp.com*/
    ResponseSearchPeople rootObject = JsonConvert.DeserializeObject<ResponseSearchPeople>(apiResponse);

    StringBuilder sb = new StringBuilder();
    sb.Append("<div class=\"resultDiv\"><p>Names</p>");
    foreach (Result result in rootObject.results)
    {
        string image = result.profile_path == null ? Url.Content("~/Content/Image/no-image.png") : "https://image.tmdb.org/t/p/w500/" + result.profile_path;
        string link = Url.Action("GetPerson", "TmdbApi", new { id = result.id });
        
        sb.Append("<div class=\"result\" resourceId=\"" + result.id + "\">" + "<a href=\"" + link + "\"><img src=\"" + image + "\" />" + "<p>" + result.name + "</a></p></div>");
    }
    
    ViewBag.Result = sb.ToString();

    int pageSize = 20;
    PagingInfo pagingInfo = new PagingInfo();
    pagingInfo.CurrentPage = pageNo;
    pagingInfo.TotalItems = rootObject.total_results;
    pagingInfo.ItemsPerPage = pageSize;
    ViewBag.Paging = pagingInfo;
}
public ActionResult GetPerson(int id)
{
    /*Calling API https://developers.themoviedb.org/3/people */
    string apiKey = "3356865d41894a2fa9bfa84b2b5f59bb";
    HttpWebRequest apiRequest = WebRequest.Create("https://api.themoviedb.org/3/person/" + id + "?api_key=" + apiKey + "&language=en-US") as HttpWebRequest;

    string apiResponse = "";
    using (HttpWebResponse response = apiRequest.GetResponse() as HttpWebResponse)
    {
        StreamReader reader = new StreamReader(response.GetResponseStream());
        apiResponse = reader.ReadToEnd();
    }
    /*End*/

    /*http://json2csharp.com*/
    ResponsePerson rootObject = JsonConvert.DeserializeObject<ResponsePerson>(apiResponse);
    TheMovieDb theMovieDb = new TheMovieDb();
    theMovieDb.name = rootObject.name;
    theMovieDb.biography = rootObject.biography;
    theMovieDb.birthday = rootObject.birthday;
    theMovieDb.place_of_birth = rootObject.place_of_birth;
    theMovieDb.profile_path = rootObject.profile_path == null ? Url.Content("~/Content/Image/no-image.png") : "https://image.tmdb.org/t/p/w500/" + rootObject.profile_path;
    theMovieDb.also_known_as = string.Join(", ", rootObject.also_known_as);

    return View(theMovieDb);
}

Explanation
Let me explain you the above code of the Controller.

Get Index ActionResult: The Index Get ActionResult has 2 parameters string peopleName, int? page. I will be using this method for doing the actor search (by their names) through the API.

The peopleName will contains the value of the textbox (that contains actor’s name) while the page will contain the current page number as given in the URL.

Consider – if the URL is http://localhost:64253/TmdbApi/nicole/1 then peopleName will receive nicole while page will receive 1.

Similarly for the URL like http://localhost:64253/TmdbApi/tom%20cruise/3 the peopleName will receive tom cruise while page will receive 3.

This method calls CallAPI() which will make the actual API call. I have passed the name of the actor and the page number to this method.

Post Index ActionResult: Next moving to the Index Post ActionResult which makes the call to CallAPI() method. I pass the actor name and 0 page number, telling it to get me the 1st page for the search result.

CallAPI(): The most important is the CallAPI method where I am implementing TheMovieDb API. Here I append API key, actor’s name and page number to the API URL https://api.themoviedb.org/3/search/person.

I get the result in JSON format which is serialized into the ResponseSearchPeople class. For doing this Serialization I use JsonConvert class from namespace Newtonsoft.Json .

Then I create an HTML by extracting values from the ResponseSearchPeople class and set it to a Viewbag object. I will show this HTML in the Index view.

I am also using the PagingInfo class to create the paging links for the view.

GetPerson() Method: This method calls TheMovieDb API once more and this time it passes the actors id to it. The API sends back the JSON containing the complete information of the given actors. I will show this information inside the GetPerson view.

Create Index View

Create an Index View and add following code to it:

@model demo.MVC.Models.TheMovieDb
@using demo.MVC.Class;
<style>
    body {
        background-color: #000;
    }

    #apiDiv {
        padding-left: 20px;
    }

        #apiDiv input, #apiDiv button {
            font-size: 25px;
            color: #000;
        }

        #apiDiv h4 {
            margin: 10px 0;
            color: #00e8ff;
            font-size: 20px;
        }

        #apiDiv .textAlignCenter {
            text-align: center;
        }

            #apiDiv .textAlignCenter img {
                display: none;
                width: 100px;
            }

        #apiDiv #message {
            padding-top: 10px;
        }

            #apiDiv #message .resultDiv {
                background: #FFF;
                display: inline-block;
            }

                #apiDiv #message .resultDiv > p {
                    color: #000;
                    display: inline-block;
                    width: 95%;
                    padding: 10px;
                    border-bottom: double 2px #CCC;
                }

                #apiDiv #message .resultDiv .result {
                    width: 23%;
                    height: 240px;
                    padding: 6px;
                    float: left;
                    text-align: center;
                    cursor: pointer;
                }

                    #apiDiv #message .resultDiv .result img {
                        width: 75%;
                    }

                    #apiDiv #message .resultDiv .result p {
                        margin: 0;
                    }

                        #apiDiv #message .resultDiv .result p a {
                            color: #808080;
                            text-decoration: none;
                            font-size: 20px;
                            height: 100px;
                        }

                            #apiDiv #message .resultDiv .result p a:hover {
                                text-decoration: underline;
                            }

        #apiDiv form span {
            color: red;
            font-size: 20px;
        }

    .pagingDiv {
        background: #f2f2f2;
    }

        .pagingDiv > a {
            display: inline-block;
            padding: 0px 9px;
            margin-right: 4px;
            border-radius: 3px;
            border: solid 1px #c0c0c0;
            background: #e9e9e9;
            box-shadow: inset 0px 1px 0px rgba(255,255,255, .8), 0px 1px 3px rgba(0,0,0, .1);
            font-size: .875em;
            font-weight: bold;
            text-decoration: none;
            color: #717171;
            text-shadow: 0px 1px 0px rgba(255,255,255, 1);
        }

            .pagingDiv > a:hover {
                background: #fefefe;
                background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#FEFEFE), to(#f0f0f0));
                background: -moz-linear-gradient(0% 0% 270deg,#FEFEFE, #f0f0f0);
            }

            .pagingDiv > a.active {
                border: none;
                background: #616161;
                box-shadow: inset 0px 0px 8px rgba(0,0,0, .5), 0px 1px 0px rgba(255,255,255, .8);
                color: #f0f0f0;
                text-shadow: 0px 0px 3px rgba(0,0,0, .5);
            }
</style>
<div id="apiDiv">
    <h4>Enter the Search Text and Press Submit Button</h4>
    @using (Html.BeginForm())
    {
        @Html.EditorFor(model => model.searchText)
        <button id="submit">Submit</button>
        @Html.ValidationMessageFor(model => model.searchText)
    }
    <div id="message">
        @(new HtmlString(ViewBag.Result))
    </div>
    <div class="pagingDiv">
        @{
            PagingInfo pagingInfo = (PagingInfo)ViewBag.Paging;
            if (pagingInfo != null)
            {
                @Html.PageLinks((PagingInfo)ViewBag.Paging, x => Url.Action("Index", "TmdbApi", new { peopleName = Model.searchText, page = x }))
            }
        }
    </div>
</div>

Explanation
I am using some CSS to make it look good – in design terms. The View has a search textbox and a button from where you can do the API search for the actors. The result is shown inside the message div.

The pagination links are shown in the pagingDiv div.

Since I will be using the classes kept in the Class folder therefore I have used this line – @using demo.MVC.Class; on top of the View.

Create GetPerson View

Create a new View and give it the name GetPerson. Add the following codes to it:

@model demo.MVC.Models.TheMovieDb
<style>
    body {
        background-color: #000;
    }

    #apiDiv {
        padding-left: 20px;
        display: inline-block;
        width: 95%;
        text-align: justify;
    }

        #apiDiv h4 {
            margin: 10px 0;
        }

        #apiDiv .biography img {
            float: left;
            padding-right: 10px;
        }

        #apiDiv .return {
            text-align: center;
        }

            #apiDiv .return a {
                color: #00e8ff;
                font-size: 20px;
                text-decoration: underline;
            }
</style>
<div id="apiDiv">
    <div class="return"><a href="@Url.Action("Index", "TmdbApi")">Return</a></div>
    <h4>@Model.name</h4>
    <p class="biography"><img src="@Model.profile_path" />@Model.biography</p>
    <p>Birthday: @Model.birthday</p>
    <p>Place of Birth: @Model.place_of_birth</p>
    <p>Also Known as: @Model.also_known_as</p>
</div>

Explanation
This view will show an actor’s complete information by calling TheMovieDb API.

Add Routing Rules

Add the below rules in your RouteConfig.cs file:

routes.MapRoute(
    name: "TmdbApi",
    url: "TmdbApi/{id}/",
    defaults: new { controller = "TmdbApi", action = "GetPerson", id = "" },
    constraints: new { id = @"^[0-9]+$" }
);

routes.MapRoute(
    name: "TmdbApiPaging",
    url: "TmdbApi/{peopleName}/{page}",
    defaults: new { controller = "TmdbApi", action = "Index", peopleName = "", page = "" },
    constraints: new { peopleName = @"^[a-zA-Z]+$", page = @"^[0-9]+$" }
);

Explanation
The work of these rules is to create a URL structure that is given below:

For searching through actors – http://localhost:64253/TmdbApi/actorName/page

For fetching a particular actor’s information – http://localhost:64253/TmdbApi/982722.

DEMO DOWNLOAD

For additional local denver seo consulting visit tacticalseoconsulting.

Share this article -

yogihosting

ABOUT THE AUTHOR

This article has been written by the Technical Staff of YogiHosting. Check out other articles on “WordPress, SEO, jQuery, HTML” and more.