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.
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:
[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.
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.
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.