Faactory.RestClient 0.1.7

There is a newer version of this package available.
See the version list below for details.
dotnet add package Faactory.RestClient --version 0.1.7
NuGet\Install-Package Faactory.RestClient -Version 0.1.7
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Faactory.RestClient" Version="0.1.7" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Faactory.RestClient --version 0.1.7
#r "nuget: Faactory.RestClient, 0.1.7"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Faactory.RestClient as a Cake Addin
#addin nuget:?package=Faactory.RestClient&version=0.1.7

// Install Faactory.RestClient as a Cake Tool
#tool nuget:?package=Faactory.RestClient&version=0.1.7

REST Client for .NET

This projects contains the implementation for a REST Client for .NET. It's built on top of the original HttpClient and fully supports IHttpClientFactory for dependency injection.

Getting started

Install the package.

$ dotnet add package Faactory.RestClient

To create a client instance using dependency injection

IServiceCollection services = new ServiceCollection()
    ...
    .AddRestClient( "jsonplaceholder", "https://jsonplaceholder.typicode.com" )
    ...

This will give you access to an IRestClientFactory interface. Then, wherever you need a client

public class MyClass
{
    private readonly RestClient client;

    public MyClass( IRestClientFactory clientFactory )
    {
        client = clientFactory.CreateClient( "jsonplaceholder" );
    }
    ...
}

If creating the client manually, an HttpClient instance needs to be passed through

var httpClient = ...
var restClient = new RestClient( httpClient, "https://jsonplaceholder.typicode.com" );

Using

All request operations respond with a RestResponse or RestObjectResponse, containing the status code of the operation and the content, if any.

var response = await restClient.GetAsync( "todos/1" );

if ( response.IsOk() )
{
    // do something with the content only if response is a 200 OK
}

Customization and Scoping

It is possible to customize and/or scope an operation by creating a request before execution. We do that by invoking Configure with or without the path to the resource. This allows us to configure the headers, or the query parameters. The method returns a RestRequest instance.

Note: If we create a scoped request and then invoke the operation with an url, the latter overrides the scoped url.

Here's an example of a scoped request

var response = await restClient.Configure( "users", options =>
{
    options.QueryParameters.Add( "address.city", "Bartholomebury" );
})
.GetAsync();

And another one of a non-scoped request

var response = await restClient.Configure( options =>
{
    options.Headers.Add( "X-Custom-Header", "custom header value" );
})
.GetAsync( "users" );

Both scoped and non-scoped request instances are reusable and multiple operations can be performed with the same instance. Here's an example on reusing a non-scoped request.

var request = restClient.Configure( options =>
{
    options.Headers.Add( "X-Custom-Header", "custom header value" );
} );

var ids = new int[] { 1, 2, 3 };

var getTasks = ids.Select( id => request.GetAsync( $"users/{id}" ) )
    .ToArray();

var responses = await Task.WhenAll( getTasks );

Working with JSON

The client includes extensions to serialize and deserialize JSON content. This can be done by manually deserializing a RestResponse instance

var response = await restClient.GetAsync( "todos/1" );

var todo = response.Deserialize<Todo>();

Or requesting directly with the JSON extension, which returns a RestObjectResponse instead

var response = await restClient.GetJsonAsync<Todo>( "todos/1" );

var todo = response.Content;

In both scenarios you will have access to the response status code and headers.

Polymorphic JSON Serialization

By default, the client uses Microsoft's JSON serializer, therefore, there is limited support for polymorphic serialization and deserialization is not supported at all. You can find more information in this article where you will also find a few workarounds, including writing a custom converter.

If you rather use Newtonsoft's Json.NET (or any other), you can easilly write a custom serializer. Here's an example for Newtonsoft's

public class NewtonsoftJsonSerializer : ISerializer
{
    public byte[] SerializeObject<T>( T value )
    {
        var json = JsonConvert.SerializeObject( value );

        return Encoding.UTF8.GetBytes( json );
    }
    
    public T DeserializeObject<T>( byte[] content )
    {
        var json = Encoding.UTF8.GetString( content );

        return JsonConvert.DeserializeObject<T>( json );
    }
}

If you are using dependency injection, you can add the serializer by injecting it into the container services.

IServiceCollection services = new ServiceCollection()
...
services.AddRestClient( "jsonplaceholder", "https://jsonplaceholder.typicode.com" )

// add our custom serializer
services.AddSingleton<IJsonSerializer, NewtonsoftJsonSerializer>();

If you are not using dependency injection, just pass it into the constructor.

var httpClient = ...
var restClient = new RestClient( 
    httpClient,
    "https://jsonplaceholder.typicode.com",
    new NewtonsoftJsonSerializer() );

You can also pass a custom serializer if deserializing from a RestResponse instance

var customSerializer = new NewtonsoftJsonSerializer();

var response = await restClient.GetAsync( "todos/1" );

var todo = response.Deserialize<Todo>( customSerializer );

Authorization header

Since version 0.1.4 you can use extensions to configure the Authorization header. Currently, the supported schemes are

  • Basic authentication
  • Bearer token

This can be applied to the entire client, when configuring the underlying HttpClient instance with dependency injection

IServiceCollection services = new ServiceCollection()
    ...
    .AddRestClient( "jsonplaceholder", "https://jsonplaceholder.typicode.com", httpClient =>
    {
        options.AddBasicAuthentication( "username", "password" );
    } )
    ...

when manually creating the client instance, by accessing the underlying client extensions

var httpClient = ...

httpClient.AddBasicAuthentication( "username", "password" );

var restClient = new RestClient( httpClient, "https://jsonplaceholder.typicode.com" );

// accessing the underlying client instance works the same
// restClient.HttpClient.AddBasicAuthentication( "username", "password" );

or when customizing/scoping a request

var response = await restClient.Configure( "users", options =>
{
    options.AddBasicAuthentication( "username", "password" );
})
.GetAsync();

Note: These extensions require adding the namespace Faactory.RestClient

EXPERIMENTAL: REST-Schema Extensions

If you are working with an API that is compatible with REST-Schema, there are a few extensions that you can use. These are experimental features, so they might change in the future, disappear or not function properly.

We can send a map schema spec through the headers by customizing a request with the available extensions.

var response = await restClient.Configure( "users", options =>
{
    options.SchemaMap( new {
        spec = new {
            _ = new string[] { "id", "name", "email", "address" },
            address = new string[] { "street", "city", "zipcode" }
        }
    } );
})
.GetAsync();

Similarly we can send an include schema spec.

var response = await restClient.Configure( "users", options =>
{
    options.SchemaInclude( new {
        spec = new {
            _ = new string[] { "address" }
        }
    } );
})
.GetAsync();
Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Faactory.RestClient:

Package Downloads
Fonix.Extensions.ApiClient

Fonix APIs RestClient Extensions

Faactory.DbContext.RestSql

DbContext RestSql provider

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.4.0-preview-1 107 7/26/2023
0.3.2 243 7/10/2023
0.3.1 155 5/4/2023
0.3.0 602 8/9/2022
0.3.0-preview-6 116 8/9/2022
0.3.0-preview-5 147 8/9/2022
0.3.0-preview-4 112 8/8/2022
0.3.0-preview-2 114 8/5/2022
0.3.0-preview-1 115 8/5/2022
0.2.1 653 3/28/2022
0.1.8 605 11/3/2021
0.1.7 270 10/7/2021
0.1.6 303 8/12/2021
0.1.5 271 8/12/2021
0.1.4 320 8/3/2021
0.1.3 352 7/29/2021
0.1.2 374 7/27/2021
0.1.1 277 7/21/2021
0.1.0 285 7/21/2021