Skip to main content

Introducing Core Library in C#

· 4 min read

APIMatic has introduced core library to provide a stable runtime that powers all functionality of our SDKs. In this release, we have revamped our C# SDKs to improve the code quality and provide better test coverage.

note

This feature is not yet released. We are publishing this changelog in advance to help solicit feedback and to help customers prepare for a major Code Generator update.

Refer to Introducing core libraries in APIMatic generated SDKs changelog to understand the importance of core library in our SDKs.

Core Library

The core library consists of classes that are used to make up the C# SDK. They help the SDKs to create and execute requests and responses using the best practices of C# language.

Some of the main features that core library introduces in our C# SDKs are:

  • Processing of the request
  • Request creation
  • Execution of the request
  • Response handling
  • Unit testing

This feature is rigorously tested to guarantee the highest level of speed and stability. Implementation of core library for C# SDK is placed at APIMatic.Core GitHub repository.

Benefits of Core Library in C# SDKs

Here are the benefits of introducing core library in C# SDKs.

HttpClientWrapper

We moved HttpClientWrapper to core library. HttpClientWrapper uses the Microsoft HttpClient to send the requests and receive the responses from a resource identified by a URI. It is being injected by IClientConfiguration. This way it applies the required configuration while sending the requests and receiving the responses. Doing this helps to test the core library functionary a 100%.

Improved SDK

The C# SDK is now lighter in size. All utilities have been moved to the core library and all responsibilities of the request creation and response handling also lie within the core library, making SDKs clean and easy to maintain.

Cleaner API call

The finest benefit added to our C# SDKs through the introduction of core library is simplified and cleaner API call code. In addition to moving all of the serialization, deserialization, and request parameter validation code into the core library, we have also included the code for executing API calls and handling errors. This results in a cleaner API call. Plus, applying authorization parameters to the requests also introduces abstraction.

Before, a C# endpoint looked like this:

/// <summary>
/// Send Date Array EndPoint.
/// </summary>
/// <param name="dates">Required parameter: Example: .</param>
/// <returns>Returns the Models.ServerResponse response from the API call.</returns>
public Models.ServerResponse SendDateArray(
List<DateTime> dates)
{
Task<Models.ServerResponse> t = this.SendDateArrayAsync(dates);
ApiHelper.RunTaskSynchronously(t);
return t.Result;
}

/// <summary>
/// Send Date Array EndPoint.
/// </summary>
/// <param name="dates">Required parameter: Example: .</param>
/// <param name="cancellationToken"> cancellationToken. </param>
/// <returns>Returns the Models.ServerResponse response from the API call.</returns>
public async Task<Models.ServerResponse> SendDateArrayAsync(
List<DateTime> dates,
CancellationToken cancellationToken = default)
{
// validating required parameters.
if (dates == null)
{
throw new ArgumentNullException("dates", "The parameter \"dates\" is a required parameter and cannot be null.");
}

// the base uri for api requests.
string baseUri = this.Config.GetBaseUri();

// prepare query string for API call.
StringBuilder queryBuilder = new StringBuilder(baseUri);
queryBuilder.Append("/body/date");

// prepare specfied query parameters.
var queryParams = new Dictionary<string, object>()
{
{ "array", "true" },
};

// append request with appropriate headers and parameters
var headers = new Dictionary<string, string>()
{
{ "accept", "application/json" },
{ "Content-Type", "application/json" },
};

// append body params.
var bodyText = ApiHelper.JsonSerialize(dates, new CustomDateTimeConverter("yyyy'-'MM'-'dd"));

// prepare the API call request to fetch the response.
HttpRequest httpRequest = this.GetClientInstance().PostBody(queryBuilder.ToString(), headers, bodyText, queryParameters: queryParams);

if (this.HttpCallBack != null)
{
this.HttpCallBack.OnBeforeHttpRequestEventHandler(this.GetClientInstance(), httpRequest);
}

// invoke request and get response.
HttpStringResponse response = await this.GetClientInstance().ExecuteAsStringAsync(httpRequest, cancellationToken: cancellationToken).ConfigureAwait(false);
HttpContext context = new HttpContext(httpRequest, response);
if (this.HttpCallBack != null)
{
this.HttpCallBack.OnAfterHttpResponseEventHandler(this.GetClientInstance(), response);
}

// return null on 404.
if (response.StatusCode == 404)
{
return null;
}

// handle errors defined at the API level.
this.ValidateResponse(response, context);

return ApiHelper.JsonDeserialize<Models.ServerResponse>(response.Body);
}

Now, because of core library, a C# SDK endpoint looks like this:

/// <summary>
/// Send Date Array EndPoint.
/// </summary>
/// <param name="dates">Required parameter: Example: .</param>
/// <returns>Returns the Models.ServerResponse response from the API call.</returns>
public Models.ServerResponse SendDateArray(
List<DateTime> dates)
=> CoreHelper.RunTask(SendDateArrayAsync(dates));

/// <summary>
/// Send Date Array EndPoint.
/// </summary>
/// <param name="dates">Required parameter: Example: .</param>
/// <param name="cancellationToken"> cancellationToken. </param>
/// <returns>Returns the Models.ServerResponse response from the API call.</returns>
public async Task<Models.ServerResponse> SendDateArrayAsync(
List<DateTime> dates,
CancellationToken cancellationToken = default)
=> await CreateApiCall<Models.ServerResponse>()
.RequestBuilder(_requestBuilder => _requestBuilder
.Setup(HttpMethod.Post, "/body/date")
.Parameters(_parameters => _parameters
.Body(_bodyParameter => _bodyParameter.Setup(dates).Serializer(_value => CoreHelper.JsonSerialize(_value, new CustomDateTimeConverter("yyyy'-'MM'-'dd"))).Required())
.Header(_header => _header.Setup("Content-Type", "application/json"))
.Query(_query => _query.Setup("array", "true"))))
.ResponseHandler(_responseHandler => _responseHandler
.NullOn404()
.Deserializer(_response => ApiHelper.JsonDeserialize<Models.ServerResponse>(_response)))
.ExecuteAsync(cancellationToken);