- C#
- Python
- NodeJS
Address Validation International C# Code Snippet
using System;
using System.Threading.Tasks;
using AVIReference;
namespace address_validation_international_dot_net.SOAP
{
/// <summary>
/// Provides functionality to call the ServiceObjects Address Validation International (AVI) SOAP service's GetAddressInfo operation,
/// retrieving validated and corrected international address information with fallback to a backup endpoint for reliability in live mode.
/// </summary>
public class GetAddressInfoValidation
{
private const string LiveBaseUrl = "https://sws.serviceobjects.com/avi/soap.svc/SOAP";
private const string BackupBaseUrl = "https://swsbackup.serviceobjects.com/avi/soap.svc/SOAP";
private const string TrialBaseUrl = "https://trial.serviceobjects.com/avi/soap.svc/SOAP";
private readonly string _primaryUrl;
private readonly string _backupUrl;
private readonly int _timeoutMs;
private readonly bool _isLive;
/// <summary>
/// Initializes URLs, timeout, and IsLive.
/// </summary>
public GetAddressInfoValidation(bool isLive)
{
_timeoutMs = 10000;
_isLive = isLive;
_primaryUrl = isLive ? LiveBaseUrl : TrialBaseUrl;
_backupUrl = isLive ? BackupBaseUrl : TrialBaseUrl;
if (string.IsNullOrWhiteSpace(_primaryUrl))
throw new InvalidOperationException("Primary URL not set.");
if (string.IsNullOrWhiteSpace(_backupUrl))
throw new InvalidOperationException("Backup URL not set.");
}
/// <summary>
/// This operation returns validated and corrected international address information for a given address,
/// including formatted address lines, locality, administrative area, postal code, country details, and additional information components.
/// </summary>
/// <param name="Address1">Address line 1 of the international address.</param>
/// <param name="Address2">Address line 2 of the international address. Optional.</param>
/// <param name="Address3">Address line 3 of the international address. Optional.</param>
/// <param name="Address4">Address line 4 of the international address. Optional.</param>
/// <param name="Address5">Address line 5 of the international address. Optional.</param>
/// <param name="Locality">The city, town, or municipality of the address. Required if postal code is not provided.</param>
/// <param name="AdministrativeArea">The state, region, or province of the address. Required if postal code is not provided.</param>
/// <param name="PostalCode">The postal code of the address. Required if locality and administrative area are not provided.</param>
/// <param name="Country">The country name or ISO 3166-1 Alpha-2/Alpha-3 code.</param>
/// <param name="OutputLanguage">The language for service output (e.g., "ENGLISH", "BOTH", "LOCAL_ROMAN", "LOCAL").</param>
/// <param name="LicenseKey">The license key to authenticate the API request.</param>
public async Task<AddressInfoResponse> GetAddressInfo(string Address1, string Address2, string Address3, string Address4, string Address5, string Locality, string AdministrativeArea, string PostalCode, string Country, string OutputLanguage, string LicenseKey)
{
AVISoapServiceClient clientPrimary = null;
AVISoapServiceClient clientBackup = null;
try
{
// Attempt Primary
clientPrimary = new AVISoapServiceClient();
clientPrimary.Endpoint.Address = new System.ServiceModel.EndpointAddress(_primaryUrl);
clientPrimary.InnerChannel.OperationTimeout = TimeSpan.FromMilliseconds(_timeoutMs);
AddressInfoResponse response = await clientPrimary.GetAddressInfoAsync(
Address1, Address2, Address3, Address4, Address5, Locality, AdministrativeArea, PostalCode, Country, OutputLanguage, LicenseKey).ConfigureAwait(false);
if (_isLive && !ValidResponse(response))
{
throw new InvalidOperationException("Primary endpoint returned null or a fatal TypeCode=3 error for GetAddressInfo");
}
return response;
}
catch (Exception primaryEx)
{
try
{
clientBackup = new AVISoapServiceClient();
clientBackup.Endpoint.Address = new System.ServiceModel.EndpointAddress(_backupUrl);
clientBackup.InnerChannel.OperationTimeout = TimeSpan.FromMilliseconds(_timeoutMs);
return await clientBackup.GetAddressInfoAsync(
Address1, Address2, Address3, Address4, Address5, Locality, AdministrativeArea, PostalCode, Country, OutputLanguage, LicenseKey).ConfigureAwait(false);
}
catch (Exception backupEx)
{
throw new InvalidOperationException(
$"Both primary and backup endpoints failed.\n" +
$"Primary error: {primaryEx.Message}\n" +
$"Backup error: {backupEx.Message}");
}
finally
{
clientBackup?.Close();
}
}
finally
{
clientPrimary?.Close();
}
}
private static bool ValidResponse(AddressInfoResponse response)
{
return response?.Error == null || response.Error.TypeCode != "3";
}
}
}
Address Validation International Python Code Snippet
from suds.client import Client
from suds import WebFault
from suds.sudsobject import Object
class GetAddressInfoSoap:
def __init__(self, license_key: str, is_live: bool = True, timeout_ms: int = 15000):
"""
license_key: Service Objects AVI license key.
is_live: Whether to use live or trial endpoints.
timeout_ms: SOAP call timeout in milliseconds.
"""
self.is_live = is_live
self.timeout = timeout_ms / 1000.0
self.license_key = license_key
# WSDL URLs
self._primary_wsdl = (
"https://sws.serviceobjects.com/avi/soap.svc?wsdl"
if is_live
else "https://trial.serviceobjects.com/avi/soap.svc?wsdl"
)
self._backup_wsdl = (
"https://swsbackup.serviceobjects.com/avi/soap.svc?wsdl"
if is_live
else "https://trial.serviceobjects.com/avi/soap.svc?wsdl"
)
def get_address_info(
self,
address1: str,
address2: str,
address3: str,
address4: str,
address5: str,
locality: str,
administrative_area: str,
postal_code: str,
country: str,
output_language: str,
) -> Object:
"""
Calls the GetAddressInfo SOAP API to retrieve validated and corrected international address information.
Parameters:
address1: Address line 1 of the international address.
address2: Address line 2 of the international address. Optional.
address3: Address line 3 of the international address. Optional.
address4: Address line 4 of the international address. Optional.
address5: Address line 5 of the international address. Optional.
locality: The city, town, or municipality of the address. Required if postal code is not provided.
administrative_area: The state, region, or province of the address. Required if postal code is not provided.
postal_code: The postal code of the address. Required if locality and administrative area are not provided.
country: The country name or ISO 3166-1 Alpha-2/Alpha-3 code.
output_language: The language for service output (e.g., "ENGLISH", "BOTH", "LOCAL_ROMAN", "LOCAL").
license_key: Your ServiceObjects license key.
is_live: Determines whether to use the live or trial servers.
timeout_ms: Timeout, in milliseconds, for the call to the service.
Returns:
suds.sudsobject.Object: SOAP response containing validated address details or error.
Raises:
RuntimeError: If both primary and backup endpoints fail.
"""
# Common kwargs for both calls
call_kwargs = dict(
Address1=address1,
Address2=address2,
Address3=address3,
Address4=address4,
Address5=address5,
Locality=locality,
AdministrativeArea=administrative_area,
PostalCode=postal_code,
Country=country,
OutputLanguage=output_language,
LicenseKey=self.license_key,
)
# Attempt primary
try:
client = Client(self._primary_wsdl, timeout=self.timeout)
# Override endpoint URL if needed:
# client.set_options(location=self._primary_wsdl.replace('?wsdl','/soap'))
response = client.service.GetAddressInfo(**call_kwargs)
# If response invalid or Error.TypeCode == "3", trigger fallback
if response is None or (
hasattr(response, "Error")
and response.Error
and response.Error.TypeCode == "3"
):
raise ValueError("Primary returned no result or Error.TypeCode=3")
return response
except (WebFault, ValueError, Exception) as primary_ex:
# Attempt backup
try:
client = Client(self._backup_wsdl, timeout=self.timeout)
response = client.service.GetAddressInfo(**call_kwargs)
if response is None:
raise ValueError("Backup returned no result")
return response
except (WebFault, Exception) as backup_ex:
msg = (
"Both primary and backup endpoints failed.\n"
f"Primary error: {str(primary_ex)}\n"
f"Backup error: {str(backup_ex)}"
)
raise RuntimeError(msg)
Address Validation International NodeJS Code Snippet
var args = {Address1: 'Address1',
Address2: 'Address2',
Address3: 'Address3',
Address4: 'Address4',
Address5: 'Address5',
Locality: 'Locality',
AdministrativeArea: 'AdministrativeArea',
PostalCode: 'PostalCode',
Country: 'Country',
OutputLanguage: 'OutputLanguage',
LicenseKey: 'LicenseKey'};
soap.createClient(primaryUrl, function(err, client) {
client.GetAddressInfo(args, function(err, result) {
//This is where you will handle the service results. Your business logic will determine
//how the validated information is used.
//The exact output can be found in our documentation:
//https://www.serviceobjects.com/docs/dots-address-validation-international/
if(err != null || result == null)
{
//There was an error that occurred that wasn't part of the normal service response
return;
}
else{
import { soap } from 'strong-soap';
/**
* <summary>
* A class that provides functionality to call the ServiceObjects Address Validation International (AVI) SOAP service's GetAddressInfo endpoint,
* retrieving validated and corrected international address information with fallback to a backup endpoint for reliability in live mode.
* </summary>
*/
class GetAddressInfoSoap {
/**
* <summary>
* Initializes a new instance of the GetAddressInfoSoap class with the provided input parameters,
* setting up primary and backup WSDL URLs based on the live/trial mode.
* </summary>
* @param {string} Address1 - Address line 1 of the international address.
* @param {string} Address2 - Address line 2 of the international address. Optional.
* @param {string} Address3 - Address line 3 of the international address. Optional.
* @param {string} Address4 - Address line 4 of the international address. Optional.
* @param {string} Address5 - Address line 5 of the international address. Optional.
* @param {string} Locality - The city, town, or municipality of the address. Required if postal code is not provided.
* @param {string} AdministrativeArea - The state, region, or province of the address. Required if postal code is not provided.
* @param {string} PostalCode - The postal code of the address. Required if locality and administrative area are not provided.
* @param {string} Country - The country name or ISO 3166-1 Alpha-2/Alpha-3 code.
* @param {string} OutputLanguage - The language for service output (e.g., "ENGLISH", "BOTH", "LOCAL_ROMAN", "LOCAL").
* @param {string} LicenseKey - Your license key to use the service.
* @param {boolean} isLive - Value to determine whether to use the live or trial servers.
* @param {number} timeoutSeconds - Timeout, in seconds, for the call to the service.
* @throws {Error} Thrown if LicenseKey is empty or null.
*/
constructor(Address1, Address2, Address3, Address4, Address5, Locality, AdministrativeArea, PostalCode, Country, OutputLanguage, LicenseKey, isLive = true, timeoutSeconds = 15) {
if (!LicenseKey) {
throw new Error('LicenseKey cannot be empty or null.');
}
this.args = {
Address1,
Address2,
Address3,
Address4,
Address5,
Locality,
AdministrativeArea,
PostalCode,
Country,
OutputLanguage,
LicenseKey
};
this.isLive = isLive;
this.timeoutSeconds = timeoutSeconds;
this.LiveBaseUrl = 'https://sws.serviceobjects.com/avi/soap.svc?wsdl';
this.BackupBaseUrl = 'https://swsbackup.serviceobjects.com/avi/soap.svc?wsdl';
this.TrialBaseUrl = 'https://trial.serviceobjects.com/avi/soap.svc?wsdl';
this._primaryWsdl = this.isLive ? this.LiveBaseUrl : this.TrialBaseUrl;
this._backupWsdl = this.isLive ? this.BackupBaseUrl : this.TrialBaseUrl;
}
/**
* <summary>
* Asynchronously calls the GetAddressInfo SOAP endpoint, attempting the primary endpoint
* first and falling back to the backup if the response is invalid (Error.TypeCode == '3') in live mode
* or if the primary call fails.
* </summary>
* @returns {Promise<Object>} A promise that resolves to an object containing validated address details or an error.
* @throws {Error} Thrown if both primary and backup calls fail, with detailed error messages.
*/
async invokeAsync() {
try {
const primaryResult = await this._callSoap(this._primaryWsdl, this.args);
if (this.isLive && !this._isValid(primaryResult)) {
console.warn("Primary returned Error.TypeCode == '3', falling back to backup...");
const backupResult = await this._callSoap(this._backupWsdl, this.args);
return backupResult;
}
return primaryResult;
} catch (primaryErr) {
try {
const backupResult = await this._callSoap(this._backupWsdl, this.args);
return backupResult;
} catch (backupErr) {
throw new Error(`Both primary and backup calls failed:\nPrimary: ${primaryErr.message}\nBackup: ${backupErr.message}`);
}
}
}
/**
* <summary>
* Performs a SOAP service call to the specified WSDL URL with the given arguments,
* creating a client and returning the raw SOAP response data.
* </summary>
* @param {string} wsdlUrl - The WSDL URL of the SOAP service endpoint (primary or backup).
* @param {Object} args - The arguments to pass to the GetAddressInfo method.
* @returns {Promise<Object>} A promise that resolves to the raw SOAP response data.
* @throws {Error} Thrown if the SOAP client creation fails, the service call fails, or the response cannot be parsed.
*/
_callSoap(wsdlUrl, args) {
return new Promise((resolve, reject) => {
soap.createClient(wsdlUrl, { timeout: this.timeoutSeconds * 1000 }, (err, client) => {
if (err) return reject(err);
client.GetAddressInfo(args, (err, result) => {
const response = result?.GetAddressInfoResult;
try {
if (!response) {
return reject(new Error("SOAP response is empty or undefined."));
}
resolve(response);
} catch (parseErr) {
reject(new Error(`Failed to parse SOAP response: ${parseErr.message}`));
}
});
});
});
}
/**
* <summary>
* Checks if a SOAP response is valid by verifying that it exists and either has no Error object
* or the Error.TypeCode is not equal to '3'.
* </summary>
* @param {Object} response - The response object to validate.
* @returns {boolean} True if the response is valid, false otherwise.
*/
_isValid(response) {
return response && (!response.Error || response.Error.TypeCode !== '3');
}
}
export { GetAddressInfoSoap }; //Check for an error object
if(result.GetAddressInfoResult.Error != null)
{
//An error object was returned by the service and you will want to use
//the following failover logic.
//If it was a Service Objects Fatal exception we recommend trying
//a backup server.
if(result.GetAddressInfoResult.Error.TypeCode == "3")
{
//The actual backup url will be provided when you purchase a license key
var backupUrl = 'https://trial.serviceobjects.com/avi/soap.svc?wsdl';
soap.createClient(backupUrl, function(failoverErr, backupClient) {
backupClient.GetAddressInfo(args, function(failoverErr, failoverResult) {
//Handle the failoverErr or failoverResult objects.
return;
});
});
}
else{
//The Error object isn't of the type "Service Objects Fatal" so
//there is no need to use the failover logic. There was some Error of
//type Authorization, User Input, or Domain Specific.
response.writeHead(200, "OK", {'Content-Type': 'text/html'});
response.end(JSON.stringify(result));
return;
}
}
else{
//You have a non Error response.
//All of the data will reside within the result object
//As an easy to see what the service returns I am returning a JSON
//serialized version as the response.
response.writeHead(200, "OK", {'Content-Type': 'text/html'});
response.end(JSON.stringify(result));
return;
}
}
});
});