Let’s be honest, checking out this tutorial means you are looking for how to simplify your HTTP-Based REST API interactions with Refit. I can’t blame you for that. We all want a more convenient way to get the job done. Good news is, you are about to satisfy your curiosity; but first, let’s understand Refit.
Understanding Refit
Refit is a library that allows you to define REST API interfaces as C# interfaces. It leverages the power of .NET’s HTTPClient and provides a simple and elegant way to interact with HTTP-based APIs. With Refit, you can define your API endpoints as methods in an interface, and Refit takes care of generating the necessary HTTP requests, serialising and deserialising JSON payloads, and handling response data. Refit acts as a wrapper around these interface methods. This not only saves us a significant amount of work but also allows for more efficient management of dependencies.
Getting Started with Refit
To start using Refit, you need to add the Refit NuGet package to your project. Once added, you can define your API interfaces and use them to make HTTP requests. Refit takes care of generating the implementation code for your interfaces at runtime.
Examples
Above is an example of an interface `IUserAPI` (1), with a method called `GetUsers` (2). The `[Get(“/users”)]` attribute specifies that this method corresponds to an HTTP GET request with the endpoint `/users`. Refit will utilise this information whenever the `GetUsers` method is invoked.
Now, let’s see the “live interface” in action.
In a nutshell, the GetUsers() method is asynchronously called, retrieving a list of users. The program then outputs the names of the users. Refit was then invoked to streamline the process of making HTTP requests, handling serialisation/deserialisation, and simplifying API interactions in a clean and maintainable manner. And that’s it! The beauty of using Refit is that it takes care of handling the requests and mapping the responses for us.
Now, let’s explore some additional features and functionalities offered by Refit.
HTTP Attributes: In the previous example, we utilized the `[Get]` attribute, which represents an HTTP GET method. Refit provides a total of six HTTP attributes: `[Get]`, `[Post]`, `[Put]`, `[Delete]`, `[Patch]`, and `[Head]`. These attributes can be used to specify the HTTP method for a particular interface method. The request URL can be either static or dynamic. By specifying a parameter as a URL substitution, Refit treats it as a route parameter as presented below:
If the parameter name in the method signature differs from the name used in the attribute, you can utilize the `[AliasAs]` attribute to establish the connection as shown below:
When no URL substitution is provided, Refit treats all parameters as query parameters. This is shown below:
For GET requests, you can simply pass an object as a parameter, and Refit will automatically convert all its non-null public properties into query parameters as illustrated below:
To specify a request body in the interface method, you can use the `[Body]` attribute before the corresponding parameter. Note that a method can have only one `[Body]` parameter. See an example below:
To add static headers, the `[Headers]` attribute can be applied to the method. This can be done as illustrated below:
However, if you want to add the same header to all methods within the interface, you can apply the `[Headers]` attribute to the interface itself. This can be done as illustrated below:
Meanwhile, For dynamic header values, you can use the `[Header]` attribute before the corresponding method parameter. See an example below:
To set multiple headers simultaneously, you can employ the `[HeaderCollection]` attribute. See an example below:
It is, therefore, important to note that headers with the same name can override each other. The priority is as follows: interface attribute (lowest priority), method attribute (normal priority), and method parameter attribute (highest priority).
To delete a header, assign it an empty value. This can be done as follows:
Furthermore, Refit allows for easy file uploads in various formats, such as Stream, ByteArray, and FileInfo. To upload a file, add the `[Multipart]` attribute to the method and wrap the file parameter using the appropriate wrapper attribute, such as `[ByteArrayPart]`, `[StreamPart]`, or `[FileInfoPart]`. See an example below:
Lastly, when using Refit, you may encounter different exceptions. By default, when the response status code indicates an unsuccessful request, Refit throws an `ApiException`. However, you can modify this behavior if needed. For example, if your API returns a status 200 even for unsuccessful requests, you can wrap your response types with `ApiResponse<T>` to gain control over the response object.
While it is possible to override the default exception factory, it’s important to note that it won’t be helpful in catching exceptions raised during response deserialisation.
Finally Thought!
This tutorial has been able to explore several important features and functionalities of the Refit library in C#. Well, this is how Refit can be utilised to simplify interaction with HTTP-based REST APIs while focusing more on the logic and structure of the code. I hope this guide has been helpful to you. Thank you for reading.
About Michael Andifon Etim:
Michael is an experienced software engineer that has led several software development teams. He has coached and mentored tech talents across Africa and beyond.