Making Faster API Calls Using Refit Rest Library

Introduction

Refit is a rest library written in C# and available as a NuGet package. It is designed to make faster HTTP calls with less code. It has a specific syntax that we have to follow in our services/classes in order to make API calls. In this article, we will learn how we can use Refit to make API calls. For that, we will create a simple API project with some API calls. Then we will create a Blazor Web Assembly project that will call APIs using the Refit library. 

Web API project with APIs

First of all, I will create an ASP.NET Core Web API project.

On the next screen, give your app a name and then select a .NET version (I am using .NET 6 in this article). Also, don't forget to check OpenAPI checkbox - it will add swagger to API.

When the project is created, add a class Person in your models' folder with the following properties:

public class Person {
    public int Id {
        get;
        set;
    }
    public string FullName {
        get;
        set;
    } = string.Empty;
    public string Email {
        get;
        set;
    } = string.Empty;
    public string City {
        get;
        set;
    } = string.Empty;
    public string Country {
        get;
        set;
    } = string.Empty;
}

Create a controller PersonsController and add the following data:

[Route("api/[controller]")]
[ApiController]
public class PersonsController: ControllerBase {
    private static List < Person > persons = new List < Person > () {
        new Person {
            Id = 1, FullName = "Usman", Email = "usman@gmail.com", City = "Mirpur", Country = "Pakistan"
        },
        new Person {
            Id = 2, FullName = "Jolly", Email = "jolly@gmail.com", City = "Rome", Country = "Italy"
        },
        new Person {
            Id = 3, FullName = "Tina", Email = "tina@gmail.com", City = "Berlin", Country = "Germany"
        },
        new Person {
            Id = 4, FullName = "Anil", Email = "anil@gmail.com", City = "Mumbai", Country = "India"
        },
    };
    // GET: api/<PersonsController>
    [HttpGet]
    public IEnumerable < Person > Get() {
        return persons;
    }
    // GET api/<PersonsController>/5
    [HttpGet("{id}")]
    public Person Get(int id) {
        return persons.Where(x => x.Id == id).FirstOrDefault();
    }
    // POST api/<PersonsController>
    [HttpPost]
    public void Post([FromBody] Person person) {
        persons.Add(person);
    }
    // PUT api/<PersonsController>/5
    [HttpPut("{id}")]
    public void Put(int id, [FromBody] Person person) {
        persons.Remove(persons.Where(x => x.Id == id).FirstOrDefault());
        persons.Add(person);
    }
    // DELETE api/<PersonsController>/5
    [HttpDelete("{id}")]
    public void Delete(int id) {
        persons.Remove(persons.Where(x => x.Id == id).FirstOrDefault());
    }
}

Run the application. If everything is okay, your browser will look like following:

CORS (Cross-Origin Resource Sharing)

To make API calls from any other API or project, we have to tell our Web API by allowing CORS. Go to your Program.cs (If you are using a lower version, go to startup.cs file) and add the following code:

//Where registering services
builder.Services.AddCors(policy => {
    policy.AddPolicy("OpenCorsPolicy", opt => opt.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
});
//app configurations
app.UseCors("OpenCorsPolicy");

Creating frontend project

The API is working fine. Now, I will create a Blazor Web Assembly Project as a frontend app and will consume APIs in it using Rift.

Create a new Blazor Web Assembly project.

Run the project to check if it is working. Then, install Refit Packages from Nuget.

In the models' folder, create a Person model with the same properties as those in your Web API project.

public class Person {
    public int Id {
        get;
        set;
    }
    public string FullName {
        get;
        set;
    } = string.Empty;
    public string Email {
        get;
        set;
    } = string.Empty;
    public string City {
        get;
        set;
    } = string.Empty;
    public string Country {
        get;
        set;
    } = string.Empty;
}

Create a service class that will make API calls using Rift. Add the code below in it:

using Refit;
using Refit_UI_App.Models;
namespace Refit_UI_App.Services {
    public interface IPersonApiService {
        [Get("/Persons")]
        Task < List < Person >> GetPersons();
        [Get("/Persons/{id}")]
        Task < Person > GetPerson(int id);
        [Post("/Persons")]
        Task NewPerson([Body] Person guest);
        [Put("/Persons/{id}")]
        Task UpdatePerson(int id, [Body] Person guest);
        [Delete("/Persons/{id}")]
        Task DeletePerson(int id);
    }
}

Rift has its syntax. On every method, the [Get] attribute with the same method name (API name) will be added. This attribute will tell the method to call that API. For example, in the API project we have /Persons API, which will return all Persons. So in [Get("/Persons")], we added it with the same name. Similarly, with all other methods, we provided the same API name to call that API. It is important to use the same name.

Now in your Program.cs file, we have to tell the application to use IPersonApiService to call APIs using Refit. For that, add the following code to your Program.cs file:

builder.Services.AddRefitClient<IPersonApiService>().ConfigureHttpClient(x =>
{
    x.BaseAddress = new Uri("https://localhost:7212/api");
});

Then in your razor page Index.razor, add the following code on top of the page:

@page "/"
@using Refit_UI_App.Models
@using Refit_UI_App.Services
@inject IPersonApiService personsService;

The above code snippet is for the Models and Services folder. Then, we inject the IPersonApiService class that we will be using. After the above code, add the following HTML code:

<PageTitle>Persons</PageTitle>

<h1>Persons!</h1>

Welcome to your new app.
<table class="table table-bordered">
    <thead>
        <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Email</th>
            <th>Location</th>
            <th>Action</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in persons)
        {
            <tr>
                <td>@item.Id</td>
                <td>@item.FullName</td>
                <td>@item.Email</td>
                <td>@(item.City+", "+item.Country)</td>
                <td>
                    <button class="btn btn-primary" @onclick="@(e => AddPerson(item))">Add Guest</button>
                    <button class="btn btn-warning" @onclick="@(e => UpdatePerson(item))">Update Guest</button>
                    <button class="btn btn-danger" @onclick="@(e => DeletePerson(item))">Delete Guest</button>
                </td>
            </tr>
        }
    </tbody>
</table>

The above code will display records and action buttons. After this, add the following code at the bottom of your Index.razor page, within @code block.

@code {
    List < Person > persons = new List < Person > ();
    protected override async Task OnInitializedAsync() {
        persons = await personsService.GetPersons();
        if (persons == null) {
            persons = new List < Person > ();
        }
    }
    private async Task AddPerson(Person person) {
        await personsService.NewPerson(new Person {
            Id = persons.Count + 1,
                FullName = person.FullName,
                City = "Tokyo",
                Country = "Japan",
                Email = person.Email
        });
        persons = await personsService.GetPersons();
    }
    private async Task UpdatePerson(Person person) {
        person.FullName = "Batista";
        await personsService.UpdatePerson(person.Id, person);
        persons = await personsService.GetPersons();
    }
    private async Task DeletePerson(Person guest) {
        await personsService.DeletePerson(guest.Id);
        persons = await personsService.GetPersons();
    }
}

Run both projects at the same time. This is done because the Frontend project will call the API project to get/post data. API project also must be running. After the successful running of both projects, the browser will look like the following:

We call methods from IPersonApiService class, which is calling APIs using Refit and sending us a response that is displayed on the page. Add, Update and Delete buttons also use APIs to perform specific operations.

The source code is more than 25MB and cannot be uploaded with this article. If you want to get code download it from GitHub.

Thank you.