Go to content

Bulletcode.NET

API Client

Bulletcode.NET provides a built-in service for communicating with a REST API. In order to use it, add a reference to the Bulletcode.Client package and call the AddApiClient() extension method of IServiceCollection:

services.AddApiClient();

The ApiClientOptions class contains settings for the API client. They can be changed by passing a callback to the AddApiClient() method, or by adding a ApiClientOptions section to the appsettings.json file.

  • BaseAddress — specifies the base URL for the API.
  • Timeout — specifies the default timeout for API requests. The default value is 30 seconds.
  • AcceptedRetryAfter — specifies the default delay after which a request is resent after receiving an Accepted response. The default value is 10 seconds.

The API client uses the same JSON serialization options as the API server implemented using Bulletcode.Web.Core. See JSON Serialization for more information.

When a request fails and the server returns an ErrorResult response, the API client throws an ErrorResultException containing the information about the error, in addition to the standard properties of the HttpRequestException. Otherwise, a plain HttpRequestException is thrown. See API Errors for more information.

IApiClient service

The IApiClient service can be used to perform requests to the API. It contains the following methods:

  • GetAsync() — performs a GET request to the given URL, with optional query string parameters, and deserializes the JSON response as an object.
  • DownloadAsync() — performs a GET request to the given URL, with optional query string parameters, and returns the response as a byte array.
  • PostAsync() — performs a POST request to the given URL. The object passed as the request body is serialized into JSON. A byte array can also be specified as the request body. When the result type is specified, the response is deserialized as an object of the given type; otherwise, the response is ignored.
  • PutAsync() — performs a PUT request to the given URL. This method is analogous to PostAsync().
  • PatchAsync() — performs a PATCH request to the given URL. This method is analogous to PostAsync().
  • DeleteAsync() — performs a DELETE request to the given URL. This method doesn’t use any request body and ignores the response body.

The following options can be specified for all requests:

  • Authentication — the type of the authentication token to use (see API Authentication below). By default, the access token is used.
  • Timeout — an optional custom timeout for the request. If not specified, the value from ApiClientOptions is used.
  • HandleAcceptedResponse — when set to true, the API client automatically resends the request after receiving a response with Accepted status code. See Background Jobs for information about handling such requests on the server side. The default value is false.
  • AcceptedRetryAfter — an optional delay after which a request is resent. If not specified, the value from ApiClientOptions is used.

Additional options for DownloadAsync():

  • Accept — the optional Accept header; an HttpRequestException is thrown when the content type of the server’s response doesn’t match the specified value.
  • RangeFrom — the optional start of the range to download.
  • RangeTo — the optional end of the range to download.

Additional options for PostAsync() and PutAsync() methods with binary body:

  • ContentType — the content type of the request. By default, "application/octet-stream" is used. The server should be configured to access the request data for the specified content type as binary data (see MVC for more information).

Query string helper

The QueryStringSerializer helper class contains the following static methods for handling NameValueCollection objects:

  • Serialize() — converts an object into a NameValueCollection in such way that it can be deserialized from the query string on the server side. DateTime values are serialized using the "yyyy-MM-dd" format; enum values are serialized as numbers; null values are ignored; all other values are converted to culture invariant strings. This method is useful when performing a GET request with a complex query string.
  • ToString() — converts a NameValueCollection to a properly escaped string, including the leading '?'. An empty string is returned if the collection is empty.

API authentication

In order for the API authentication to work, the application must provide a service implementing the IAuthenticationProvider interface. It has a single method, AuthenticateAsync(), which should add the authentication header to the request.

The API client supports two types of authentication tokens: the access token represents an authenticated user, and the optional refresh token can be used to obtain a new access token when it expires. By default, the access token is used. The Authentication option passed to a method of the IApiClient can be used to select the refresh token or skip authentication.

Bulletcode.Client provides two classes that can be used as base classes for authentication providers:

  • AuthenticationProvider can be used for applications which use both the access token and the refresh token. When an API request is being made, this class checks if the access token is still valid and refreshes it if it has expired. This is useful in case of mobile application, which can be inactive for an extended period of time.
  • AuthenticationService is a background service, which periodically refreshes the access token to prevent it from expiring. It doesn’t use a separate refresh token. This is useful for desktop applications which can maintain a constant connection to the server.

Both classes call the abstract RefreshTokensAsync() method when the access token needs to be refreshed. This method should either call SetToken() and return true when a new token or pair of tokens are obtained, or call ClearToken() and return false if the token couldn’t be refreshed.

The class which inherits AuthenticationService should be registered as a singleton and as a hosted service, for example by calling:

services.AddHostedService( provider => provider.GetRequiredService<AccountService>() );

See also Token authentication for more information about implementing authentication for the API server.