Conga Product Documentation

Welcome to the new doc site. Some of your old bookmarks will no longer work. Please use the search bar to find your desired topic.

HttpHelper

Use HttpHelper to communicate with third-party services over HTTP from custom code. HttpHelper provides asynchronous methods to perform standard HTTP operations such as GET, POST, PUT, PATCH, and DELETE. It supports both generic (T) and raw HttpResponseMessage responses, giving you flexibility in handling external API responses. It also supports per-request customization using HttpRequestOptions, which allows you to pass additional headers dynamically for individual requests.

Best Practices

  • Ensure the external endpoint is added to the Trusted-API configuration.
  • Use retry logic to handle transient failures.
  • Always set appropriate headers and request timeouts.
  • Create the HttpHelper instance only once and reuse it across classes.
  • Create the HttpHelper instance only in the main implementation class and pass it to other classes as needed.
  • Use HttpRequestOptions when headers need to vary per request.
  • Use certificate-based authentication for secure APIs when required.

Getting an Instance

You can create an instance of HttpHelper using the ExternalApiAttributes class. This allows you to configure headers, retry logic, timeouts, and certificates.
Note: To use the custom retry feature, ensure you are using Conga.Platform.Extensibility.Library version 202409.2.88 or later.
  • Basic Usage: Use this option when you only need to specify the base URL of the external service.
    ExternalApiAttributes externalApiAttributes = new("https://external-system-url");
    var httpHelper = base.GetHttpHelper(externalApiAttributes);
    

    Use Case: Simple GET or POST requests without custom headers or retry logic.

  • With Headers: Use this option when the external API requires custom headers such as authentication tokens.
    Dictionary<string, string> headers = new() { /* define headers */ };
    ExternalApiAttributes externalApiAttributes = new("https://external-system-url", headers);
    var httpHelper = base.GetHttpHelper(externalApiAttributes);
    

    Use case: APIs that require headers like Authorization, Content-Type, or custom keys.

  • With Retry Options: Use this option to enable automatic retries for transient failures.
    ExternalApiAttributes externalApiAttributes = new("https://external-system-url")
    {
        Retry = new Retry
        {
            IsEnabled = true,
            Count = 2 // Limit is 1–3
        },
        RequestTimeout = 10
    };
    var httpHelper = base.GetHttpHelper(externalApiAttributes);
    

    Use case: APIs that may fail intermittently due to network or rate-limiting issues.

  • With Retry Disabled: Use this option when retrying requests is not recommended.
    ExternalApiAttributes externalApiAttributes = new("https://external-system-url")
    {
        Retry = new Retry
        {
            IsEnabled = false
        },
        RequestTimeout = 10
    };
    var httpHelper = base.GetHttpHelper(externalApiAttributes);
    

    Use case: APIs where retries could cause duplicate operations.

  • With Certificate Info: Use this option when the external API requires client certificate authentication.
    Dictionary<string, string> headers = new()
    {
        { "client_id", Config.ClientId },
        { "client_secret", Config.ClientSecret }
    };
    ExternalApiAttributes externalApiAttributes = new("https://apis.test.com", headers)
    {
        BaseUri = "https://apis.test.com",
        Certificates = new()
        {
            new CertificateInfo
            {
                RawData = Convert.FromBase64String(certString),
                Password = certPassword
            }
        },
        Retry = new Retry { IsEnabled = false }
    };
    var httpHelper = GetHttpHelper(externalApiAttributes);
    

    Use case: Secure APIs that require mutual TLS authentication.

    Recommendation: Create the HttpHelper instance once in the main implementation class and pass it to other classes. HttpHelper instances cannot be created outside the main implementation class.

Reference

GET Methods

Method

Description

Task<T> GetAsync<T>(string requestUri)Sends a GET request and deserializes the response into type T.
Task<HttpResponseMessage> GetAsync(string requestUri)Sends a GET request and returns the raw HTTP response.
Task<T> GetAsync<T>(string requestUri, HttpRequestOptions options)Sends a GET request with request options and deserializes the response.
Task<HttpResponseMessage> GetAsync(string requestUri, HttpRequestOptions options)Sends a GET request with request options and returns the raw response.
POST Methods

Method

Description

Task<T> PostAsync<T>(string requestUri, HttpContent content)Sends a POST request and deserializes the response.
Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content)Sends a POST request and returns the raw response.
Task<T> PostAsync<T>(string requestUri, HttpContent content, HttpRequestOptions options)Sends a POST request with request options and deserializes the response.
Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content, HttpRequestOptions options)Sends a POST request with request options and returns the raw response.
PUT Methods

Method

Description

Task<T> PutAsync<T>(string requestUri, HttpContent content)Sends a PUT request and deserializes the response.
Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content)Sends a PUT request and returns the raw response.
Task<T> PutAsync<T>(string requestUri, HttpContent content, HttpRequestOptions options)Sends a PUT request with request options and deserializes the response.
Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content, HttpRequestOptions options)Sends a PUT request with request options and returns the raw response.
PATCH Methods

Method

Description

Task<T> PatchAsync<T>(string requestUri, HttpContent content)Sends a PATCH request and deserializes the response.
Task<HttpResponseMessage> PatchAsync(string requestUri, HttpContent content)Sends a PATCH request and returns the raw response.
Task<T> PatchAsync<T>(string requestUri, HttpContent content, HttpRequestOptions options)Sends a PATCH request with request options and deserializes the response.
Task<HttpResponseMessage> PatchAsync(string requestUri, HttpContent content, HttpRequestOptions options)Sends a PATCH request with request options and returns the raw response.
DELETE Methods

Method

Description

Task<HttpResponseMessage> DeleteAsync(string requestUri)Sends a DELETE request and returns the raw response.
Task<HttpResponseMessage> DeleteAsync(string requestUri, HttpContent content)Sends a DELETE request with content and returns the raw response.
Task<HttpResponseMessage> DeleteAsync(string requestUri, HttpRequestOptions options)Sends a DELETE request with request options and returns the raw response.
Task<HttpResponseMessage> DeleteAsync(string requestUri, HttpContent content, HttpRequestOptions options)Sends a DELETE request with request options and returns the raw response.

Examples

The following examples demonstrate common scenarios for using HttpHelper in custom code. These examples are for reference only and illustrate how to configure HttpHelper, send HTTP requests, and handle responses when communicating with external services.

GET API Call

This example demonstrates how to use HttpHelper to send a GET request to an external API and deserialize the response into a strongly typed object. It also shows how to configure headers, disable retry logic, and log the response output.
string baseAddress = "https://jsonplaceholder.typicode.com";
Dictionary<string, string> headers = new Dictionary<string, string>() { //define headers };
ExternalApiAttributes externalApiAttributes = new(baseAdderess, headers)
{
    Retry = new Retry()
    {
        IsEnabled = false
    },
    RequestTimeout = 10
};
var httpHelper = GetHttpHelper(externalApiAttributes);
var logHelper = GetLogHelper();

string url = "/todos/1";
var response = await httpHelper.GetAsync<SampleResponse>(url);
logHelper.LogDebug(response);
Console Output:
Complete-GetAsync(https://jsonplaceholder.typicode.com/todos/1), HttpStatus=OK, Time=285.534
{"userId":1,"id":1,"title":"delectus aut autem","completed":false}

POST API Call

This example demonstrates how to send data to an external API using a POST request. It shows how to retrieve data using a GET request, modify the response payload, serialize the request body, and submit it using HttpHelper.
string baseAddress = "https://jsonplaceholder.typicode.com";
Dictionary<string, string> headers = new Dictionary<string, string>() { //define headers };
ExternalApiAttributes externalApiAttributes = new(baseAdderess, headers)
{
    Retry = new Retry()
    {
        IsEnabled = true,
        Count = 2
    },
    RequestTimeout = 20
};
var httpHelper = GetHttpHelper(externalApiAttributes);
var logHelper = GetLogHelper();

string url = "/todos/1";
var response = await httpHelper.GetAsync<SampleResponse>(url);

url = "/todos";
response.id = 0;
response.title = "Callback";
var contentToPost = new StringContent(JsonConvert.SerializeObject(response),Encoding.UTF8,"application/json");
var postResult = await httpHelper.PostAsync<SampleResponse>(url,contentToPost);
logHelper.LogDebug(postResult);
Console Output:
Complete-GetAsync(https://jsonplaceholder.typicode.com/todos/1), HttpStatus=OK, Time=285.534
{"userId":1,"id":1,"title":"delectus aut autem","completed":false}
Complete-PostAsync(https://jsonplaceholder.typicode.com/todos), HttpStatus=Created, Time=400.073
{"userId":1,"id":201,"title":"Callback","completed":false}

Passing Additional Headers Using HttpRequestOptions

This example demonstrates how to pass request-specific headers using HttpRequestOptions. Use this approach when headers vary between requests and should not be configured globally while creating the HttpHelper instance.
using Conga.Platform.Extensibility.CustomCode.Library;
using Conga.Platform.Extensibility.CustomCode.Library.Models;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using CustomHttpRequestOptions = Conga.Platform.Extensibility.CustomCode.Library.Models.HttpRequestOptions;

namespace CustomApi.Template
{
    public class SampleAccount : CodeExtensibility
    {
        public async Task<string> GetBadgeInfoAsync(CancellationToken cancellationToken)
        {
            ThrowIfCancellationRequested(cancellationToken);
            string requestUri = "/MyBadge";
            string baseRequestUri = "https://dummyjson.com";
            ExternalApiAttributes externalApiAttributes = new ExternalApiAttributes(baseRequestUri);
            Dictionary<string, string> additionalHeaders = new Dictionary<string, string>()
            {
                {"x-name", "Test" }
            };
            var httpHelper = base.GetHttpHelper(externalApiAttributes);

            var response = await httpHelper.GetAsync(requestUri,
                new CustomHttpRequestOptions()
                {
                    AdditionalHeaders = additionalHeaders
                });
            return await response.Content.ReadAsStringAsync();
        }

        

        public async Task<string> PostExternalAsync(CancellationToken cancellationToken)
        {
            ThrowIfCancellationRequested(cancellationToken);
            string requestUri = "https://dummyjson.com/products/add";
            ExternalApiAttributes externalApiAttributes = new ExternalApiAttributes(requestUri);
            var httpHelper = base.GetHttpHelper(externalApiAttributes);

            Dictionary<string, string> data = new()
            {
                {"title", "BMW Pencil" },
                {"description", "BMW Pencils" },
                {"brand", "BMW" }
            };
            Dictionary<string, string> additionalHeaders = new Dictionary<string, string>()
            {
                { "x-header", "sample-host" }
            };
            HttpContent httpContent = new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
            var response = await httpHelper.PostAsync(requestUri, httpContent, new CustomHttpRequestOptions()
            {
                AdditionalHeaders = additionalHeaders
            });
            return await response.Content?.ReadAsStringAsync();
        }
      


        public async Task<string> PutExternalAsync(CancellationToken cancellationToken)
        {
            ThrowIfCancellationRequested(cancellationToken);
            string requestUri = "https://dummyjson.com/products/1";
            ExternalApiAttributes externalApiAttributes = new ExternalApiAttributes(requestUri);
            var httpHelper = base.GetHttpHelper(externalApiAttributes);

            Dictionary<string, string> data = new()
            {
                {"title", "BMW Pencil" },
                {"description", "iPhone Galaxy +1" },
                {"brand", "iPhone" }
            };
            Dictionary<string, string> additionalHeaders = new Dictionary<string, string>()
            {
                { "x-host", "sample-host" }
            };
            HttpContent httpContent = new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
            var response = await httpHelper.PutAsync(requestUri, httpContent, new CustomHttpRequestOptions()
            {
                AdditionalHeaders = additionalHeaders
            });
            return await response.Content?.ReadAsStringAsync();
        }

        public async Task<string> PatchExternalHttpContentAsync(CancellationToken cancellationToken)
        {
            ThrowIfCancellationRequested(cancellationToken);
            string requestUri = "https://dummyjson.com/products/1";
            ExternalApiAttributes externalApiAttributes = new ExternalApiAttributes(requestUri);
            var httpHelper = base.GetHttpHelper(externalApiAttributes);

            Dictionary<string, string> data = new()
            {
                {"description", "iPhone Galaxy latest" },
                {"brand", "iPhone" }
            };
            Dictionary<string, string> additionalHeaders = new Dictionary<string, string>()
            {
                { "x-test", "sample-host" }
            };
            HttpContent httpContent = new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
            var response = await httpHelper.PatchAsync(requestUri, httpContent, new CustomHttpRequestOptions()
            {
                AdditionalHeaders = additionalHeaders
            });
            return await response.Content?.ReadAsStringAsync();
        }
      
        public async Task<string> DeleteExternalAsync(CancellationToken cancellationToken)
        {
            ThrowIfCancellationRequested(cancellationToken);
            string requestUri = "https://dummyjson.com/products/1";
            ExternalApiAttributes externalApiAttributes = new ExternalApiAttributes(requestUri);
            var httpHelper = base.GetHttpHelper(externalApiAttributes);

            Dictionary<string, string> additionalHeaders = new Dictionary<string, string>()
            {
                { "x-host", "sample-host" }
            };

            var response = await httpHelper.DeleteAsync(requestUri, new CustomHttpRequestOptions()
            {
                AdditionalHeaders = additionalHeaders
            });
            return await response.Content?.ReadAsStringAsync();
        }
      
    }
}