RestClient.Net is a powerful .NET REST API client that features task-based async, strong types, and dependency injection support for all platforms. Use it to consume ASP.NET Core Web APIs or interact with RESTful APIs over the internet in C#, F#, or Visual Basic. It's designed with functional-style programming and F# in mind.
NuGet: RestClient.Net
This release updates all dependencies and targets major versions of .NET: 4.5, 5, 6, and 7.
- First-class URLs: Utilizes Urls to treat URLs as immutable records with a fluent API for construction.
- Dependency Injection Support: Easily mock REST calls and add RestClient.Net to your IoC container with a single line of code.
- Async-Friendly: All operations use async and await keywords.
- Automatic Serialization: Automatically serializes request/response bodies to/from strong types (JSON, Binary, SOAP, Google Protocol Buffers). The library is decoupled from Newtonsoft, allowing you to use any serialization method or version of Newtonsoft. This means compatibility with any version of Azure Functions.
- Cross-Platform Compatibility: Install from NuGet on any platform from .NET Framework 4.5 up to .NET 5. Supports Xamarin (Mono, iOS, Android), UWP, WebAssembly, and Unity with .NET Standard 2.0.
- HTTP Methods: Supports GET, POST, PUT, PATCH, DELETE, and custom methods.
- Fluent API: Provides a fluent API for construction, non-destructive mutation, and URL construction.
- Logging: Uses .NET Core Logging -
ILogger
for logging all aspects of HTTP calls. - Thread Safety: Immutable client for thread safety.
- High-Quality Code: Tight code and complete test coverage allow you to make changes if needed.
For a complete set of examples, see these unit tests.
using var client =
//Build the Url from the host name
new Client("jsonplaceholder.typicode.com".ToHttpsUriFromHost());
UserPost userPost = await client.PostAsync<UserPost, UserPost>(
//POST the UserPost to the server
new UserPost { title = "Title" }, "posts"
);
Dependency Injection (RestClient.Net.DependencyInjection NuGet Package)
var serviceCollection = new ServiceCollection()
//Add a service which has an IClient dependency
.AddSingleton<IGetString, GetString1>()
//Add RestClient.Net with a default Base Url of http://www.test.com
.AddRestClient((o) => o.BaseUrl = "http://www.test.com".ToAbsoluteUrl());
//Use HttpClient dependency injection
_ = serviceCollection.AddHttpClient();
public class GetString1 : IGetString
{
public IClient Client { get; }
public GetString1(IClient client) => Client = client;
public async Task<string> GetStringAsync() => await Client.GetAsync<string>();
}
public class GetString2 : IGetString
{
public IClient Client { get; }
public GetString2(CreateClient createClient)
{
//Use the options to set the BaseUrl or other properties on the Client
Client = createClient("test", (o) => { o.BaseUrl = o.BaseUrl with { Host = "www.test.com" }; });
}
public async Task<string> GetStringAsync() => await Client.GetAsync<string>();
}
//This constructs an AbsoluteUrl from the string, makes the GET call, and deserializes the JSON to a strongly typed list
//The response also contains a Client with the base of the Url that you can reuse
//Note: not available on .NET 4.5
var response = await "https://restcountries.eu/rest/v2"
.ToAbsoluteUrl()
.GetAsync<List<RestCountry>>();
using RestClient.Net.Abstractions.Extensions;
using System.Collections.Generic;
using System.Threading.Tasks;
using Urls;
namespace RestClient.Net
{
public static class GitHubGraphQLMethods
{
public static async Task<T> GetIssues<T>(string repo, string accessToken)
=> (await "https://api.github.com/graphql"
.ToAbsoluteUrl()
.PostAsync<QueryResponse<T>, QueryRequest>(
new QueryRequest("{ search(query: \"repo:" + repo + "\", type: ISSUE, first: 100) {nodes {... on Issue { number title body } } }}")
, HeadersExtensions.FromBearerToken(accessToken)
.Append("User-Agent", "RestClient.Net"))).Response.Body.data.search;
}
public record QueryRequest(string query);
public record Issue(int? number, string title, string body);
public record Issues(List<Issue> nodes);
public record Data<T>(T search);
public record QueryResponse<T>(Data<T> data);
}
[<TestMethod>]
member this.TestComposition () =
let uri =
"host.com".ToHttpUrlFromHost(5000)
.AddQueryParameter("fieldname1", "field<>Value1")
.WithCredentials("username", "password")
.AddQueryParameter("FieldName2", "field<>Value2")
.WithFragment("frag")
.WithPath("pathpart1", "pathpart2")
Assert.AreEqual("http://username:password@host.com:5000/pathpart1/pathpart2?fieldname1=field%3C%3EValue1&FieldName2=field%3C%3EValue2#frag",uri.ToString());