No matter how you choose to pronounce it, GIFs are a fantastic technology of our modern age. A correctly selected GIF can bring laughter, joy, and even comfort to both sender and recipient alike.

Over the last several years, every application has dabbled with GIFs, and to be honest with you, a chat client without GIF support is just sad. Who supply’s us with life-giving GIF support? Why Giphy, of course!

In this beginner tutorial, we’ll be building a Giphy search tool powered by Razor Pages.

What Is Giphy?

Giphy is a repository of what feels like every conceivable GIF available on the internet.

As the first and largest GIF search engine that serves more than 10 billion GIFs per day, it’s safe to say GIPHY knows GIFs. – Giphy

Giphy’s goal is to categorize GIFs on the internet and provide the user with the ability to search and serve GIFs to a recipient. Our favorite apps likely already have Giphy integration. It is improbable that anyone surfing the internet today hasn’t seen a GIF served by the service. To be sure, let’s show a GIF now!.

via GIPHY

Giphy also provides HTTP APIs and SDKs that allow developers to utilize the GIF infrastructure they have built. To continue following this post, readers should register an application at the Giphy Developer portal.

Building A Giphy Search Tool

After creating our Giphy app in the developer portal (linked above), we need to create an ASP.NET Application. In this post, we’ll be using Razor Pages. Our entire application will consist of one Razor page.

In your favorite IDE, which I hope is JetBrains Rider, create a new ASP.NET Web App. The default templates that ship with ASP.NET will create a simple Razor Pages app.

The next step is to install the GiphyDotNet NuGet package. We can install the package either through the NuGet tools in our IDE or through the command line.

dotnet add package GiphyDotNet

Once installed, we need to register our Giphy client. We can do this in our ConfigureServices method found in Startup.

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddScoped(sp =>
        new Giphy(Configuration["Giphy:ApiKey"]));
}

Next, we’ll need to add the configuration value to our appsettings.json or appsettings.Development.json file.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "Giphy" : {
    "ApiKey" : "<YOUR API KEY HERE>"
  }
}

Awesome, we’re ready to move onto our Razor PageModel. In our Index.cshtml.cs file, let’s call the Giphy API using the Giphy class.

public class IndexModel : PageModel
{
    private readonly ILogger<IndexModel> logger;
    private readonly Giphy giphy;

    [BindProperty(SupportsGet = true)]
    public string Search { get; set; }
    
    [BindProperty(SupportsGet = true)]
    public int Offset { get; set; }

    public GiphySearchResult Result { get; set; }
    public int Next => Offset + 25;
    public int Previous => Math.Min(0, Offset - 25);
    public bool HasSearch => !string.IsNullOrWhiteSpace(Search);
    public bool HasNext => Next <= Result.Pagination.TotalCount;
    public bool HasPrevious => Offset > 0;

    public IndexModel(ILogger<IndexModel> logger, Giphy giphy)
    {
        this.logger = logger;
        this.giphy = giphy;
    }

    public async Task OnGet()
    {
        Offset = Math.Max(0, Offset);
        
        if (HasSearch)
        {
            Result = await giphy.GifSearch(new SearchParameter
            {
                Query = Search,
                Offset = Offset
            });
        }
    }
}

The OnGet method utilizes the GifSearch endpoint to return values based on our search terms. We will also be allowing users to page through results with the property Offset. We could elaborate more on paging, but for this demo, the code here is adequate.

The Result property holds our search results along with the image information. We’re so close to those GIFs now! Let’s work on the UI.

In the Razor part of Index.cshtml let’s utilize Boostrap to make a presentable UI. There are a few highlights on the Razor page. We start with a search bar powered by a form utilizing a GET method. Then we display our images in a grid layout. Finally, we show some paging controls using the Pagination data returned from the Giphy API.

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}
<div class="text-center">
    <h1>Search Giphy</h1>
    <form asp-page="Index" method="get">
        <div class="input-group input-group-large">
            <div class="input-group-prepend">
                <span class="input-group-text" id="basic-addon1">
                    <i aria-hidden="true" class="fa fa-search"></i>
                </span>
            </div>
            <input asp-for="Search"
                   class="form-control"
                   type="text"
                   placeholder="Search"
                   aria-label="Search"
                   autocomplete="off"/>
            <div class="input-group-append">
                <button type="submit" class="btn btn-primary">
                    Search
                </button>
            </div>
        </div>
    </form>
</div>
<div class="container-fluid">
    @if (Model.HasSearch)
    {
        <h1 class="my-4 font-weight-bold">
            <i class="fa fa-list"></i>
            Results for "@Model.Search"
        </h1>

        <div class="masonry-layout">
            @foreach (var gif in Model.Result.Data)
            {
                <div class="masonry-layout-panel">
                    <div class="masonry-layout-panel__content">
                        <a href="@gif.BitlyUrl">
                            <img src="@gif.Images.Original.Webp" 
                                 alt="@gif.Caption"/>
                        </a>
                    </div>
                </div>
            }
        </div>

        <nav>
            <ul class="pagination pagination-circle pagination-lg justify-content-end">
                @if (Model.HasPrevious)
                {
                    <li class="page-item">
                        <a class="page-link" 
                           href="@Url.Page("Index", new {Model.Search, Offset = 0})">
                            Start
                        </a>
                    </li>
                    <li class="page-item">
                        <a class="page-link" 
                           href="@Url.Page("Index", new {Model.Search, Offset = Model.Previous})">
                            Previous
                        </a>
                    </li>
                }
                @if (Model.HasNext)
                {
                    <li class="page-item">
                        <a class="page-link" 
                           href="@Url.Page("Index", new {Model.Search, Offset = Model.Next})">
                            Next
                        </a>
                    </li>
                }
            </ul>
        </nav>
    }
</div>

We want to display our results in a masonry style grid. Masonry layout gets its name from resembling bricks stacked on top of each other. To achieve this look, we need to add some additional CSS to our site.css file (Thanks to Jhey Thompkins for the great blog post).

.masonry-layout {
  column-count: 4;
  column-gap: 0;
}
.masonry-layout-panel {
  break-inside: avoid;
  padding: 5px;
}
.masonry-layout-panel__content {
  padding: 5px;
  border-radius: 10px;
}
.masonry-layout-panel__content img {
  width: 100%;
  border-radius: 10px;
}

All the pieces are in the right place now; let’s run our application.

Conclusion

Running our application, we can now search for terms. We can also page through the results at the bottom of our masonry style grid.

Giphy Search Running in ASP.NET

This post is really for anyone looking to get started with Razor Pages and ASP.NET. While the app is simple, the immediate wow factor of seeing a page filled with GIFs is fun. The advances in CSS also make displaying a grid of things so much nicer.

For folks that want a working copy of this demo, please feel free to clone it from my Github repository and leave any feedback.