When working with a service oriented architecture, the client app interacts with multiple micro services. REST APIs are the most commonly services today and multiple Nuget packages are available which can be used to consume such remote resources over HTTP. Each Web API would need its specific authentication, default headers, JSON formatters and in addition, there would be a need to de-serialize the output to your application models. With micro-services architecture, these steps would repeat itself multiple times. Hence comes in a need to create a wrapper design around the rest clients to avoid code repetitions.
Introduction
Designing a production ready application requires removing code redundancy. In today's world where SOA and microservices have taken the front seat, almost every application needs to interact with a service and at present, the focus is on REST Web API services. In a micro services architecture, the application logic is split into multiple services, which can be independently hosted to make it scalable and brings agility to the product development. Each service would have its different base URLS, the default headers applicable, the acceptable data format (JSON or XML).
So when designing the client application, we need to create a Rest client for each microservice with its own baseurl and authentication mechanism, etc. There are few nuget packages available which provide the basic skeleton for making the Http calls to the REST APIs. For this article, I am creating the Rest client around a nuget package called RestSharp.
Refer to the abstract
class HttpRestClient.cs file. It contains Generic synchronous and async methods for Get Post Delete
and Put
.
Taking an example of the Post
method, it first creates a RestRequest
object and adds the default and specific headers configured for the RestService
. It also allows to specify the Request format, which can be Json or XML. Next, it executes the Request
using the ExecuteAsync
and Execute
method. Then, it deserializes the response to the corresponding output class.
public async Task<S> PostAsync<T, S>(string uriResource, T data,
Dictionary<string, string> headerParam = null)
where T : class
where S : new()
{
var request = GetRequestObject(Method.POST, uriResource, data, headerParam);
var response = await Client.ExecuteAsync(request);
S returnData = Deserialize<S>(response.Content);
return returnData;
}
private RestRequest GetRequestObject<T>(Method method, string uriResource,
T data = null, Dictionary<string, string> headerParam = null) where T : class
{
var request = GetRequestObject(method, uriResource, headerParam);
request.XmlSerializer = new RestSharp.Serializers.DotNetXmlSerializer();
request.AddBody(data);
return request;
}
It also supports multiple parameters to be handeled for the WebRequest
.
HttpRestClient
being an abstract
class needs to be inherited in microservice specific RestClient
, where we can initialize the baseurl for the service. In this example, it has been implemented as MicroServiceAHttpClient
.
The specific service methods can be invoked from the service Gateway as below:
public ResponseA SaveData(RequestA data)
{
var response = _httpClient.Post<RequestA, ResponseA>
("<UriResource>", data, new Dictionary<string, string> { { "UserId", "<testUserId>" }});
return response;
}
The above approach gives a very clean implementation of gateways and HttpClient
s for solution designing.
History
- 26th April, 2021: Initial version