This post is going to take you through using the DalSoft.RestClient C# library to consume a RESTful API. We are going to show you the most common scenarios using live examples from the REST API JSONPlaceholder. We are using JSONPlaceholder because it’s a great tool for testing REST clients without requiring registration or standing up your own REST API.

Let’s start.

What is DalSoft.RestClient?

From the DalSoft.RestClient website:

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

A beautiful, dynamic and fluent C# RestClient. Create frictionless code whilst still using the HttpClient you already know.

But what does that mean?

Dynamic and fluent: DalSoft.RestClient is inspired by how easy it is to consume REST APIs in other languages such as JavaScript and Python, but that doesn’t mean you can’t use it like any other library you just have more flexibility. DalSoft.RestClient uses a really easy-to-remember fluent-looking convention to access REST APIs, which allows you to interchange dynamic and strongly-typed objects easily.

Frictionless code: DalSoft.RestClient reduces the amount of ceremony and boilerplate code required to consume a REST API, most REST API calls can be done in one line of code. The resulting code is easier to read as it doesn’t overuse generics, just cast objects exactly how you would normally.

Using the HttpClient you already know: One of the strengths of DalSoft.RestClient is it doesn’t overly abstract away HttpClient you can still easily access the HttpResponseMessage. All extensibility is via DelegatingHandlers meaning everything you can do with HttpClient today you can do with DalSoft.RestClient, and better still any handlers you created for HttpClient work with DalSoft.RestClient with no code changes whatsoever.

Lastly DalSoft.RestClient is developed against .NET Standard 2.0 and is fully Cross Platform. DalSoft.RestClient works and is tested on Windows, Linux, and macOS. Xamarin is fully supported (iOS, Android, and UWP). You can use DalSoft.RestClient whether you are using .NET Core or Full framework such as .NET 4.6.

Setting up DalSoft.RestClient

You can add DalSoft.RestClient to your project by typing Install-Package DalSoft.RestClient in your package manager console, or by using .NET CLI: dotnet add package DalSoft.RestClient.

What does DalSoft.RestClient Offer?

DalSoft.RestClient is biased for creating minimalist code to access any REST/HTTP API that returns JSON – if that’s what you need you can get going with two lines of code!

For example, perform an HTTP GET on https://jsonplaceholder.typicode.com/users/1:

dynamic client = new RestClient("https://jsonplaceholder.typicode.com");  
var response = await client.Users(1).Get();

View Live Example

But that’s not all, because you extend DalSoft.RestClient using standard HttpClient DelegatingHandlers you can do anything with DalSoft.RestClient that you can with HttpClient. Here’s an example of how you would POST application/x-www-form-urlencoded data by configuring DalSoft.RestClient to use a DelegatingHandler.

var config = new Config().UseFormUrlEncodedHandler();  
  
dynamic restClient = new RestClient("https://jsonplaceholder.typicode.com", config);  
var user = new User { name="foo", email="[email protected]" };  
  
//POST name=foo&[email protected]  https://jsonplaceholder.typicode.com/users/1  
var result = await client  
      .Headers(new { ContentType = "application/x-www-form-urlencoded" })  
      .User(1)  
      .Post(user);

All responses are awaitable and you can cast them as a strongly-typed response or just leave the response as a dynamic object if you prefer it that way.

DalSoft.RestClient with DelegatingHandlers works well with strings, bytes, streams, or any other media type. Using DalSoft.RestClient you can work directly with the HttpResponseMessage or call ToString() to get the body as a string if you prefer.

Understanding the DalSoft.RestClient convention

DalSoft.RestClient is built using a Convention over Configuration approach, generally to get started with a REST API that returns JSON you new up the REST Client and provide a base URL for your request like so:
dynamic restClient = new RestClient("https://jsonplaceholder.typicode.com");

This says that for every request using restClient start with the request with the URL https://jsonplaceholder.typicode.com

Next, we use a dynamic object to express how we want to access a URL like so:
restClient.Users(1);

Let’s break it down, this is saying to use the base URL and then add Users/1 to the URL, so you end up with https://jsonplaceholder.typicode.com/Users/1

Finally, we need to tell DalSoft.RestClient what HTTP verb to use like so (for example GET or POST):
var response = restClient.Users(1).Get();

This will perform a GET on https://jsonplaceholder.typicode.com/Users/1 the accept and content type headers will be set for JSON by default. It returns a dynamic object that you can access right away – for example, response.name will return the value for the name (if it’s in the JSON of the response returned). Optionally you can cast the dynamic response object to a strongly-typed object, more on this later.

What about the convention for POST, PUT and PATCH?
var user = new { name="foo", email="[email protected]" };
var result = client.User(1).Put(user);

Breaking this down the URL is created the same way, but in the HTTP Verb, we pass an object that we want to submit to the REST API, in this case, a user. The object you pass to Post, Put and Patch can be an anonymous object or a strongly-typed object.

That’s pretty simple huh?

However… Using dynamic objects isn’t to everyone’s taste, and what if you can’t express the URL in C# syntax, simple just express it as a string like so:
var response = restClient.Resource("String-To-Add-To-The-BaseURL-Here").Resource("Can_Be_Chained_Too").Get();

HttpResponseMessage and body ToString()

It’s useful to be able to access the HttpResponseMessage directly, this is simple using DalSoft.RestClient, you can either call .HttpResponseMessage or cast the response as HttpResponseMessage.

dynamic client = new RestClient("http://jsonplaceholder.typicode.com");  
  
var result = await client.Users.Get(1);  
  
var statusCode = result.HttpResponseMessage.StatusCode; //.HttpResponseMessage  
HttpResponseMessage httpResponseMessage = result.HttpResponseMessage; // Cast as HttpResponseMessage

View Live Example

Want to get the response body as a string no problem DalSoft.RestClient has got you covered, just call .ToString() on the response.

dynamic client = new RestClient("http://jsonplaceholder.typicode.com");  
  
var response = await client.Users.Get(1);  
var responseAsString = response.ToString();

View Live Example

Query Strings

DalSoft.RestClient has a neat way to add a Query String – just append the QueryString method to your URL chain passing an anonymous object representing your QueryString:

dynamic client = new RestClient("http://jsonplaceholder.typicode.com");  
  
//http://jsonplaceholder.typicode.com/users?id=2  
await client.Users.Query(new { id = 2 }).Get();

Headers

Now you know a bit about the conventions used by DalSoft.RestClient, how do you think you add headers? You guessed it by appending the Headers method to your URL chain and passing an anonymous object. You can also pass a strongly-typed Header object or Dictionary.

Example anonymous object:

dynamic client = new RestClient("http://headers.jsontest.com/");  
  
await client  
        .Headers(new { Accept = "text/html" })  
        .Get();

Example Headers object:

dynamic client = new RestClient("http://headers.jsontest.com/");  
  
await client  
        .Headers(new Headers { { "Accept", "text/html" } })  
        .Get(1);

But what if you wanted to add the same header to every request?

Simple pass the Headers object to the DalSoft.RestClient constructor:

dynamic client = new RestClient("http://headers.jsontest.com",  
                                  new Headers (new { Accept = "text/html" })

View Live Example

How to Write Get, Post, Put/Patch, and Delete Requests

Let’s see how easy it is to access a REST API using DalSoft.RestClient!

This is where DalSoft.RestClient really shines. Fluent syntax, combined with the asynchronous execution and readability to match.

Once you understand the convention writing requests is really easy, and it produces easy to read code!

Example consume a REST API using read-only verbs GET, DELETE and HEAD:

//Perform a HTTP actions on https://jsonplaceholder.typicode.com/users/1  
dynamic client = new RestClient("https://jsonplaceholder.typicode.com");  
  
var getUserResult = await client.Users(1).Get();  
var deleteUserResult = await client.Users(1).Delete();  
await client.Users(1).Head();

View Live Example

Example POST to a REST API:

dynamic client = new RestClient("https://jsonplaceholder.typicode.com");  
  
var user = new {  name="foo", email="[email protected]", userId=10 };   
  
//POST { "name":"foo", "email":"[email protected]", "userId":10 } https://jsonplaceholder.typicode.com/users  
var result = await client.Users.Post(user);

View Live Example

Example PUT to a REST API:

dynamic client = new RestClient("https://jsonplaceholder.typicode.com");  
  
var user = new User new { name="foo", email="[email protected]" };  
  
//PUT { "name":"foo", "email":"[email protected]" }  https://jsonplaceholder.typicode.com/users/1  
var result = await client.User(1).Put(user);

View Live Example

Example PATCH to a REST API:

dynamic client = new RestClient("https://jsonplaceholder.typicode.com");  
  
var user = new User new { name="foo", email="[email protected]" };  
  
//PATCH{ "name":"foo", "email":"[email protected]" }  https://jsonplaceholder.typicode.com/users/1  
var result = await client.User(1).Patch(user);

View Live Example

You can find more usage examples in the DalSoft.RestClient GitHub repo.

Casting and Serialization

DalSoft.RestClient tries to make it as easy as possible to deserialize and cast your responses into C# models.

Casting

DalSoft.RestClient uses it’s duck typing feature to cast your response. This feature is unique to DalSoft.RestClient and not seen in other libraries. This means you don’t have to spend time creating boilerplate code to map your JSON responses to your models, just simply cast your response to your model type.

Casting to a strongly typed object:

dynamic client = new RestClient("http://jsonplaceholder.typicode.com");  
  
User user = await client.Users.Get(1);

View Live Example

Collections

So what about Collections? Again just cast the response and use as normal! Dynamically or as strongly-typed objects are supported:

This is how you can iterate over the dynamic response returned if a collection is returned from the REST API:

dynamic client = new RestClient("http://jsonplaceholder.typicode.com");  
  
var users = await client.Users.Get();  
  
foreach (var user in users)  
{  
   Console.WriteLine(user.name);  
}

View Live Example

Using the dynamic response returned you can also access by index:

dynamic client = new RestClient("http://jsonplaceholder.typicode.com");  
  
var users = await client.Users.Get();  
  
Console.WriteLine(users[0].name);

You can also cast the dynamic response returned to IList, IEnumerable, IList<T>, Array, IDictionary, IDictionary<TKey, TValue>

dynamic client = new RestClient("http://jsonplaceholder.typicode.com");  
List<User> users = await client.Users.Get();  
  
foreach (var user in users)  
{  
   Console.WriteLine("User:" + user.name);  
   Console.WriteLine("Company:" + user.company.name);  
}

View Live Example

A question came to my mind is how do I use LINQ on the dynamic response returned? Answer – cast it to List<dynamic> first:

dynamic client = new RestClient("http://jsonplaceholder.typicode.com");  
          
List<dynamic> users = await client.Users.Get();  
          
var user = users.Single(x => x.name == "Leanne Graham");  
              
Console.WriteLine(user.name);

View Live Example

Serialization

DalSoft.RestClient uses Json.NET so you can control anything about the request and response serialization using JsonSerializerSettings or Json.NET attributes. The most common scenario is wanting to “map” the JSON returned from a REST API response to your model.

And Here’s how you can map the response to your model using Json.NET attributes:

dynamic client = new RestClient("http://jsonplaceholder.typicode.com");  
  
User user = await client.Users.Get(1);   
          
public class User  
{  
   [JsonProperty("name")]  
   public string NameOfUser { get; set;}  
          
   [JsonProperty("company")]  
   public Company Company { get; set; }  
}  
  
public class Company  
{  
   [JsonProperty("name")]  
   public string NameOfCompany { get; set; }  
}

View Live Example

And to use JsonSerializerSettings pass your JsonSerializerSettings to DalSoft.RestClient like so:

// For example if the JSON returned used snake_case... We can use JsonSerializerSettings to get it deserializing correctly to our PascalCase model  
dynamic client = new RestClient("http://jsonplaceholder.typicode.com", new Config().SetJsonSerializerSettings(new JsonSerializerSettings { ContractResolver =  new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy () } })));

Extensibility

DalSoft.RestClient can be extended using HttpClient DelegatingHandlers, this means anything that works with HttpClient today will work with DalSoft.RestClient!

DelegatingHandlers

It’s really easy to use existing (or your own) DelegatingHandlers with DalSoft.RestClient.

Below is an example of how to use HttpClientHandler with DalSoft.RestClient to support cookies. Notice it works exactly the same way as HttpClient:

var cookieContainer = new CookieContainer();  
var httpClientHandler = new HttpClientHandler { CookieContainer = cookieContainer };  
  
dynamic restClient = new RestClient("https://httpbin.org/cookies/set?testcookie=restclient", new Config(httpClientHandler));  
  
await restClient.Get();  
  
Console.WriteLine(cookieContainer.GetCookies(new Uri("https://httpbin.org"))["testcookie"]?.Value);

Extending with Func delegates

DelegatingHandlers are cool but are a bit verbose to write.

Wouldn’t it be awesome if you could just use a Func delegate instead?

If you have used ASP.NET Core Middleware extensions before you will be familiar with this technique.

Here we configure DalSoft.RestClient to use a Func delegate to add a bearer token to every request. Notice again DalSoft.RestClient works with standard HttpRequestMessage and HttpResponseMessage objects.

dynamic restClient = new RestClient("http://headers.jsontest.com/", new Config()  
      .UseHandler(async (request, token, next) =>  
      {     // You can do anything to the HttpRequestMessage or HttpResponseMessage here  
            request.Headers.Add("Authorization", "Bearer your_bearer_token");   
            return await next(request, token); //Call next handler in pipeline  
      });

DelegatingHandlers that ship with DalSoft.RestClient

These handlers come with the DalSoft.RestClient package ready for you to use:

UnitTestHandler: Lets you Unit Test anything in HttpClient, no more having to spend time working out how to mock a request or response.

FormUrlEncodedHandler: Allows you to post “application/x-www-form-urlencoded” data.

MultipartFormDataHandler Allows you to post “multipart/form-data” data, which means you can post both form data and files using a .NET Stream or Byte Array.

RetryHandler Allows you to set policies for retrying transient failures.

TwitterHandler A full Twitter SDK! Shows off what can be done with DalSoft.RestClient with hardly any code!

Exception Handling and Retrying Transient Failures

Exception handling is easy in DalSoft.RestClient, you just use IsSuccessStatusCode or EnsureSuccessStatusCode in the HttpResponseMessage (like you would when using HttpClient).

For example:

dynamic client = new RestClient("https://httpstat.us/500");  
  
var response = await client.Get();   
var httpResponseMessage = response.HttpResponseMessage;   
  
if (httpResponseMessage.IsSuccessStatusCode)  
   Console.WriteLine("Success");  
else  
   Console.WriteLine("Failure by checking IsSuccessStatusCode");  
  
try  
{  
   httpResponseMessage.EnsureSuccessStatusCode();  
   Console.WriteLine("Success");     
}  
catch (HttpRequestException)  
{  
   Console.WriteLine("Exception thrown by EnsureSuccessStatusCode()");  
}

View Live Example

A common problem you will encounter when accessing a REST API is what to do about transient failures, DalSoft.RestClient supports retrying transient failures using the RetryHandler. The RetryHandler supports both exponential and Linear strategies.

The code below shows how you set an exponential policy, in this example, a transient failure would back off exponentially and retry 4 times with 2, 4, 8, 32 seconds between tries. However, because we set maxWaitToRetryInSeconds to 10 seconds we restrict the maximum amount of seconds a backoff interval can be – this stops your back off interval growing too large for example larger than your request timeout.

var config = new Config()  
   .UseRetryHandler  
   (  
     maxRetries:4,   
     waitToRetryInSeconds:2,   
     maxWaitToRetryInSeconds: 10,   
     backOffStrategy: RetryHandler.BackOffStrategy.Exponential  
   );  
  
dynamic client = new RestClient("http://jsonplaceholder.typicode.com", config);

The next example shows how you set a Linear policy, the Linear policy is easier to understand, in this example, the RetryHandler will retry a request that had a transient failure 3 times waiting 2 seconds between retries.

var config = new Config()  
   .UseRetryHandler  
   (  
     maxRetries:3,   
     waitToRetryInSeconds:2,   
     backOffStrategy: RetryHandler.BackOffStrategy.Linear   
   );  
  
dynamic client = new RestClient("http://jsonplaceholder.typicode.com", config);

Unit Testing with DalSoft.RestClient

When Unit Testing code that consumes a REST API, Mocking HttpClient can be painful. DalSoft.RestClient
has the UnitTestHandler, which lets you Mock (Fake is the correct TDD term) requests or responses easily. This simple extensibility point works great with Unit Testing your back-end services or front-end code such as Xamarin. DalSoft.RestClient uses the UnitTestHandler for its own Unit Tests too!

All you need to do is pass an instance of DalSoft.RestClient with a UnitTestHandler to your Unit Test. No need to work out how to Mock HttpClient, and you don’t even have to learn anything new you just work with a HttpRequestMessage and HttpResponseMessage.

Let’s look at a trivial example, here we ensure the JSON returned is {‘foo’:’bar’}.

var config = new Config()    
   .UseUnitTestHandler(request => new HttpResponseMessage    
   {    
      Content = new StringContent("{'foo':'bar'}")    
   });    
    
dynamic client = new RestClient("http://test.com", config);  
  
var result = await client.whatever.Get();  
  
Assert.AreEqual("{'foo':'bar'}", result.ToString());

We have just scratched the surface of what you can do with the UnitTestHandler, head over to the documentation if you want to learn more.

DalSoft.RestClient Lifetime Best Practice and IoC

It’s very easy to get the lifetime of HttpClient wrong. If you use a HttpClient with a service that gets any kind of load you will eventually hit a socket exhaustion issue. Before ASP.NET Core 2.1 the general advice was to register the HttpClient as Singleton, however, doing this you might get an issue with DNS updates if your service/app is long-running.

Knowing this limitation, and realizing that because of microservices HttpClient’s are being used more from servers the .NET Core team has come up with HttpClientFactory. The way to think of HttpClientFactory is like connection pooling for HttpClient.

DalSoft.RestClient deals with HTTP lifetime management for you, it implements IHttpClientFactory (again with the theme of not changing how you use HttpClient). So if you understand HttpClientFactories in ASP.NET Core you already know how to use them with DalSoft.RestClient.

Let’s whizz through a quick demo of how to use HttpClientFactory with DalSoft.RestClient…

First, in our ASP.NET Core project, let’s register DalSoft.RestClient as a service in Startup.cs. Here’s the simplest way to configure HttpClientFactory if you only need one DalSoft.RestClient:

public class Startup  
{  
   public void ConfigureServices(IServiceCollection services)  
   {  
      services.AddRestClient("https://api.github.com");  
   }  
}

Now all you need to do is inject IRestClientFactory into your controller:

public class GitHubController : Controller  
{  
   private readonly IRestClientFactory _restClientFactory;  
          
   public GitHubController(IRestClientFactory restClientFactory)  
   {  
      _restClientFactory = restClientFactory;  
   }  
  
   [Route("github/users/dalsoft"), HttpGet]  
   public async Task<List<repository>> CreateClient()  
   {  
      dynamic restClient = _restClientFactory.CreateClient();  
              
      var repositories = await restClient.users.dalsoft.repos.Get();  
              
      return repositories;  
   }          
}

If you need to support multiple RestClient’s we can use a named client.

Again first register your named RestClient as a service in Startup.cs

public class Startup  
{  
   public void ConfigureServices(IServiceCollection services)  
   {  
      services.AddRestClient("MyNamedGitHubClient", "https://api.github.com/orgs/");  
   }  
}

Then inject IRestClientFactory into your controller, and call the CreateClient method passing the name of your client.

public class GitHubController : Controller  
{  
   private readonly IRestClientFactory _restClientFactory;  
          
   public GitHubController(IRestClientFactory restClientFactory)  
   {  
      _restClientFactory = restClientFactory;  
   }  
  
   [Route("github/orgs/dotnet/repos"), HttpGet]  
   public async Task<List<repository>> CreateClient()  
   {  
      dynamic restClient = _restClientFactory.CreateClient("MyNamedGitHubClient"); //Get Client by name  
        
      var repositories = await restClient.dotnet.repos.Get();  
              
      return repositories;  
   }          
}

Is it worth using IRestClientFactory? If you get any sort of load YES, as it can improve your performance significantly.

Source Code

The source code for this article can be found on our GitHub repo.

Conclusion

This wraps it up for our DalSoft.RestClient library post.

DalSoft.RestClient is a very neat library that with minimal fuss or friction allows us to work with REST in our C# applications. It is simple enough to easily learn and use, and it is extensible to cover some pretty complex scenarios. Most importantly we can make use of the HttpClient knowledge we already have.

One thing we found was that DalSoft.RestClient is so easy to work with that sometimes you find yourself overcomplicating it, a simple rule is it shouldn’t take more than a couple of lines of code to do most things REST with DalSoft.RestClient.

So we hope this little demonstration will help you understand how DalSoft.RestClient works, and maybe even persuades you to try it out. We will definitely use it in our newest projects that require REST communication.

To learn about more useful ways to communicate with REST endpoints, you can check our article: A Few Great Ways to Consume RESTful API in C#.

What we’ve learned in this post:

  • What is DalSoft.RestClient, and what it can do for you?
  • How to set it up, configure it, and extend it
  • How to use the DalSoft.RestClient convention to build URLs and write requests
  • Casting and Serialization using DalSoft.RestClient
  • How easy Unit Testing is with DalSoft.RestClient
  • Best practices for IoC and HttpClient Lifetime

There is a lot more you can do with DalSoft.RestClient, check out the official documentation to find out more.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!