In this article, we’re going to learn about using RestSharp in a .NET project.

RestSharp is an open-source HTTP Client library that we can use to consume APIs easily. RestSharp features automatic serialization and deserialization, request and response type identification, and numerous authentication inbuilt patterns.

To download the source code for this article, you can visit our GitHub repository.

So, let’s get going.

RestSharp Initialization in ASP.NET Core Web API

So, how can we implement RestSharp in our application?

To start with the process, we are going to create a simple .NET 6 Web API application to consume a public API (REQ|RES) using RestSharp.

After the project creation, we have to add the required RestSharp package from the NuGet package library:

dotnet add package RestSharp

Then, let’s create a new controller and call it UsersController, and also all the required DTO classes for the API operations inside the DataTransferObjects folder. To speed things up, we’ve already created all the DTOs and you can find them all in our source code.

To continue, let’s modify our UsersController:

private readonly RestClient _client;

public UsersController()
{
    _client = new RestClient("https://reqres.in/");
}

Here we initialize the RestClient with the base URI https://reqres.in/ via the constructor. 

Handling Read Operation

To show how to get data with RestSharp, we are going to add two actions in our controller:

[HttpGet]
public async Task<IActionResult> GetUserList()
{
     var request = new RestRequest("api/users");
     var response = await _client.ExecuteGetAsync(request);

     if (!response.IsSuccessful)
     {
         //Logic for handling unsuccessful response
     }

     var userList = JsonSerializer.Deserialize<UserList>(response.Content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });

     return Ok(userList);
}

[HttpGet("{id}")]
public async Task<IActionResult> GetUser(string id)
{
     var request = new RestRequest($"api/users/{id}");
     var response = await _client.ExecuteGetAsync(request);

     if (!response.IsSuccessful)
     {
          //Logic for handling unsuccessful response
     }

     var userDetails = JsonSerializer.Deserialize<UserDetails>(response.Content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });

     return Ok(userDetails);
}

The GetUserList action returns a list of users and the GetUser action returns a single user with a specific id if the request is successful.

In each action, we initialize the request using the RestRequest class and pass a single URI parameter.

The ExecuteGetAsync method executes the GET-style request asynchronously, so we don’t have to add the HTTP method while creating the RestRequest. If our response is successful, we deserialize its content and return it to the client.

We do have an alternative to ExecuteGetAsync method that returns back our deserialized response which we have manually handled using JsonSerializer in the previous example. We can use it by modifying our GetUserList action:

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<
[HttpGet]
public async Task<IActionResult> GetUserList()
{
     var request = new RestRequest("api/users");
     var response = await _client.ExecuteGetAsync<UserList>(request);

     if (!response.IsSuccessful)
     {
         //Logic for handling unsuccessful response
     }

     return Ok(response.Data);
}

Now, we have a response with the Data property that has the deserialized response body.

It is always up to developers to use the technique that fits their project the best.

Working With Create Operation

For the CREATE operation, we are going to add a new action in our controller:

[HttpPost]
public async Task<IActionResult> AddUser([FromBody] UserForCreation userForCreation)
{
     var request = new RestRequest("api/users")
                   .AddJsonBody(userForCreation);
     var response = await _client.ExecutePostAsync<UserCreationResponse>(request);

     if (!response.IsSuccessful)
     {
         //Logic for handling unsuccessful response
     }

     return StatusCode(201, response.Data);
}

Here we create a request, and use one additional method AddJsonBody, which adds a JSON body parameter to the request. If we don’t want to add an entire object as a body parameter, we can use the AddParameter("name", "value") method, which simply adds each parameter individually.

Similarly to the ExecuteGetAsync method, the ExecutePostAsync method executes only the POST request, and we don’t have to provide the HTTP method parameter while creating the RestRequest object.

Handling Update Requests Using RestSharp

To explain how to handle the PUT request using RestSharp, let’s create an action that updates the user and job details:

[HttpPut("{id}")]
public async Task<IActionResult> UpdateUser([FromBody] UserForUpdate userForUpdate, string id)
{
     var request = new RestRequest($"api/users/{id}")
                  .AddJsonBody(userForUpdate);
     var response = await _client.ExecutePutAsync<UserUpdateResponse>(request);

     if (!response.IsSuccessful)
     {
         //Logic for handling unsuccessful response
     }

     return Ok(response.Data);
}

Similarly to the ExecuteGetAsync, and ExecutePostAsync the ExecutePutAsync  method executes only the PUT request, and we don’t have to provide the HTTP method parameter while creating the RestRequest object.

Generally, the PUT action should have a NoContent as a return, but since the API returns an object as a result of the request, we are using the OK to show the results.

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

Handling DELETE Requests with RestSharp

Lastly, let’s add one more action to our controller to show how to handle a DELETE request with RestSharp:

[HttpDelete("{id}")]
public async Task<IActionResult> DeleteUser(string id)
{
     var request = new RestRequest($"api/users/{id}", Method.Delete);
     var response = await _client.ExecuteAsync(request);

     if (!response.IsSuccessful)
     {
         //Logic for handling unsuccessful response
     }

     return NoContent();
}

There are two changes for the DELETE operation as compared to the GET, POST and PUT operations. The first change is initializing the RestRequest with the HTTP method. Here we use the Method.Delete enumeration to represent the delete operation.

Another change we have is the executing method ExecuteAsync. The method executes the request with the HTTP method supplied which is DELETE in this case. 

Additional Information About Different Methods

If we go through the official documentation, we might find a number of ways to execute HTTP requests and we might have some confusions about which one to use. So let’s discuss briefly the types and their differences.

GetAsync, PostAsync and other HTTP methods followed by Async keyword (PutAsync…) return a RestResponse with Content property and other properties like StatusCode, ContentType and so on. But if the remote server returns an error, the execution will throw an exception.

GetAsync<T>, PostAsync<T> and so on are the typed versions of the above-mentioned methods that directly deserialize the response body into the Data property. 

Talking about ExecuteGetAsync, ExecutePostAsync, ExecuteAsync and ExecutePutAsync methods, they all return a Task<RestResponse> with all the properties like StatusCode, ContentType, Content , IsSuccessful and so on. Here the Content property contains the response as a string.

Finally, we have the typed versions of the previous methods: ExecuteGetAsync<T>, ExecutePostAsync<T>, ExecuteAsync<T> and ExecutePutAsync<T>. RestSharp uses these methods to deserialize the response for us. We can find that deserialized response in the Data property. These methods will not throw an exception if the server returns an error.

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

Conclusion

In this article, we’ve learned how to use RestSharp to consume APIs in the easiest way. We’ve inspected different methods and used them to execute all the CRUD operations from our API.