- C#
- Python
- NodeJS
Name Validation 2 C# Code Snippet
using NV2Reference;
namespace name_validation_2_dot_net.SOAP
{
/// <summary>
/// Provides functionality to call the ServiceObjects DOTS Name Validation 2 SOAP service's ValidateNameV2 operation,
/// retrieving name validation information (e.g., name parsing, gender, scores) with fallback to a backup endpoint
/// for reliability in live mode.
/// </summary>
public class NameInfoV2Validation
{
private const string LiveBaseUrl = "https://sws.serviceobjects.com/NV2/api.svc/soap";
private const string BackupBaseUrl = "https://swsbackup.serviceobjects.com/NV2/api.svc/soap";
private const string TrialBaseUrl = "https://trial.serviceobjects.com/NV2/api.svc/soap";
private readonly string _primaryUrl;
private readonly string _backupUrl;
private readonly int _timeoutMs;
private readonly bool _isLive;
/// <summary>
/// Initializes URLs/timeout/IsLive.
/// </summary>
public NameInfoV2Validation(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 is the primary operation for validating and parsing a name. Given a name and optional parameters,
/// </summary>
/// <param name="Name">The name to validate (required).</param>
/// <param name="Option">Comma-separated list of options for additional processing (optional).</param>
/// <param name="LicenseKey">Your license key to use the service.</param>
/// <returns>A <see cref="Task{NameInfoV2Response}"/> containing an <see cref="NameInfoV2Response"/> object with name validation details or an error.</returns>
/// <exception cref="Exception">Thrown if both primary and backup endpoints fail.</exception>
public async Task<NameInfoV2Response> ValidateNameV2(string Name, string Option, string LicenseKey)
{
NV2LibraryClient clientPrimary = null;
NV2LibraryClient clientBackup = null;
try
{
// Attempt primary endpoint
clientPrimary = new NV2LibraryClient();
clientPrimary.Endpoint.Address = new System.ServiceModel.EndpointAddress(_primaryUrl);
clientPrimary.InnerChannel.OperationTimeout = TimeSpan.FromMilliseconds(_timeoutMs);
NameInfoV2Response response = await clientPrimary.ValidateNameV2Async(
Name, Option, LicenseKey).ConfigureAwait(false);
if (_isLive && !IsValid(response))
{
throw new InvalidOperationException("Primary endpoint returned null or a fatal TypeCode=3 error for ValidateNameV2");
}
return response;
}
catch (Exception primaryEx)
{
try
{
clientBackup = new NV2LibraryClient();
clientBackup.Endpoint.Address = new System.ServiceModel.EndpointAddress(_backupUrl);
clientBackup.InnerChannel.OperationTimeout = TimeSpan.FromMilliseconds(_timeoutMs);
return await clientBackup.ValidateNameV2Async(
Name, Option, LicenseKey).ConfigureAwait(false);
}
catch (Exception backupEx)
{
throw new Exception(
$"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 IsValid(NameInfoV2Response response) =>
response?.Error == null || response.Error.TypeCode != "3";
}
}
Name Validation 2 Python Code Snippet
from suds.client import Client
from suds import WebFault
from suds.sudsobject import Object
class NameInfoV2Soap:
def __init__(self, license_key: str, is_live: bool, timeout_ms: int = 10000):
"""
license_key: Service Objects NV2 license key.
is_live: Whether to use live or trial endpoints
timeout_ms: SOAP call timeout in milliseconds
"""
self._timeout_s = timeout_ms / 1000.0
self._is_live = is_live
self.license_key = license_key
# WSDL URLs for primary and backup endpoints
self._primary_wsdl = (
"https://sws.serviceobjects.com/NV2/api.svc?wsdl"
if is_live else
"https://trial.serviceobjects.com/NV2/api.svc?wsdl"
)
self._backup_wsdl = (
"https://swsbackup.serviceobjects.com/NV2/api.svc?wsdl"
if is_live else
"https://trial.serviceobjects.com/NV2/api.svc?wsdl"
)
def get_name_info(self, name: str, option: str) -> Object:
"""
Calls the Name Validation 2 ValidateNameV2 SOAP API to retrieve name validation information.
Parameters:
name (str): The name to validate.
option (str): Comma-separated list of options for additional processing (optional).
license_key: Service Objects Name Validation license key.
is_live: Whether to use live or trial endpoints
timeout_ms: SOAP call timeout in milliseconds
Returns:
Object: Raw SOAP response with name information or error details.
"""
# Common kwargs for both calls
call_kwargs = dict(
Name=name,
Option=option,
LicenseKey=self.license_key
)
# Attempt primary
try:
client = Client(self._primary_wsdl, timeout=self._timeout_s)
# Override endpoint URL if needed:
# client.set_options(location=self._primary_wsdl.replace('?wsdl', '/soap'))
response = client.service.ValidateNameV2(**call_kwargs)
# If response is None or fatal error code, 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 fatal Error.TypeCode=3")
return response
except (WebFault, ValueError, Exception) as primary_ex:
try:
client = Client(self._backup_wsdl, timeout=self._timeout_s)
response = client.service.ValidateNameV2(**call_kwargs)
if response is None:
raise ValueError("Backup returned no result")
return response
except (WebFault, Exception) as backup_ex:
# Raise a combined error if both attempts fail
msg = (
"Both primary and backup endpoints failed.\n"
f"Primary error: {str(primary_ex)}\n"
f"Backup error: {str(backup_ex)}"
)
raise RuntimeError(msg)
Name Validation 2 NodeJS Code Snippet
import { soap } from 'strong-soap';
import { NameInfoV2Response } from './nv2_response.js';
/**
* <summary>
* A class that provides functionality to call the ServiceObjects Name Validation 2 SOAP service's NameInfoV2 endpoint,
* retrieving name validation information with fallback to a backup endpoint for reliability in live mode.
* </summary>
*/
class NameInfoV2Soap {
/**
* <summary>
* Initializes a new instance of the NameInfoV2Soap class with the provided input parameters,
* setting up primary and backup WSDL URLs based on the live/trial mode.
* </summary>
* @param {string} Name - The name to validate.
* @param {string} Option - Comma-separated list of options for additional processing (optional).
* @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(Name, Option = '', LicenseKey, isLive = true, timeoutSeconds = 15) {
if (!LicenseKey) {
throw new Error("LicenseKey is required and cannot be empty or null.");
}
this.args = {
Name,
Option,
LicenseKey
};
this.isLive = isLive;
this.timeoutSeconds = timeoutSeconds;
this.LiveBaseUrl = "https://sws.serviceobjects.com/NV2/api.svc?wsdl";
this.BackupBaseUrl = "https://swsbackup.serviceobjects.com/NV2/api.svc?wsdl";
this.TrialBaseUrl = "https://trial.serviceobjects.com/NV2/api.svc?wsdl";
this._primaryWsdl = this.isLive ? this.LiveBaseUrl : this.TrialBaseUrl;
this._backupWsdl = this.isLive ? this.BackupBaseUrl : this.TrialBaseUrl;
}
/**
* <summary>
* Asynchronously calls the NameInfoV2 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 type="Promise<NameInfoV2Response>">A promise that resolves to a NameInfoV2Response object containing name validation details or an error.</returns>
* <exception cref="Error">Thrown if both primary and backup calls fail, with detailed error messages.</exception>
*/
async getNameInfo() {
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 processing the response into a NameInfoV2Response object.
* </summary>
* <param name="wsdlUrl" type="string">The WSDL URL of the SOAP service endpoint (primary or backup).</param>
* <param name="args" type="Object">The arguments to pass to the NameInfoV2 method.</param>
* <returns type="Promise<NameInfoV2Response>">A promise that resolves to a NameInfoV2Response object containing the SOAP response data.</returns>
* <exception cref="Error">Thrown if the SOAP client creation fails, the service call fails, or the response cannot be parsed.</exception>
*/
_callSoap(wsdlUrl, args) {
return new Promise((resolve, reject) => {
soap.createClient(wsdlUrl, { timeout: this.timeoutSeconds * 1000 }, (err, client) => {
if (err) return reject(err);
client.ValidateNameV2(args, (err, result) => {
const rawData = result?.ValidateNameV2Result;
try {
if (!rawData) {
return reject(new Error("SOAP response is empty or undefined."));
}
const parsed = new NameInfoV2Response(rawData);
resolve(parsed);
} 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 name="response" type="NameInfoV2Response">The NameInfoV2Response object to validate.</param>
* <returns type="boolean">True if the response is valid, false otherwise.</returns>
*/
_isValid(response) {
return response && (!response.Error || response.Error.TypeCode !== "3");
}
}
export { NameInfoV2Soap };
class BestGuessName {
constructor(data = {}) {
this.Prefix = data.Prefix || null;
this.FirstName = data.FirstName || null;
this.MiddleName = data.MiddleName || null;
this.LastName = data.LastName || null;
this.Suffix = data.Suffix || null;
}
toString() {
return `{Prefix: ${this.Prefix}\n` +
`FirstName: ${this.FirstName}\n` +
`MiddleName: ${this.MiddleName}\n` +
`LastName: ${this.LastName}\n` +
`Suffix: ${this.Suffix}}`;
}
}
class NameInfoV2 {
constructor(data = {}) {
this.BestGuessName = data.BestGuessName ? new BestGuessName(data.BestGuessName) : null;
this.NameIn = data.NameIn || null;
this.NameClassification = data.NameClassification || null;
this.Prefix = data.Prefix || null;
this.FirstName = data.FirstName || null;
this.MiddleName = data.MiddleName || null;
this.LastName = data.LastName || null;
this.Suffix = data.Suffix || null;
this.FirstNameFound = data.FirstNameFound || null;
this.IsCommonFirstName = data.IsCommonFirstName || null;
this.FirstNameOrigin = data.FirstNameOrigin || null;
this.FirstNameSimilar = data.FirstNameSimilar || null;
this.LastNameFound = data.LastNameFound || null;
this.IsCommonLastName = data.IsCommonLastName || null;
this.LastNameOrigin = data.LastNameOrigin || null;
this.LastNameSimilar = data.LastNameSimilar || null;
this.Gender = data.Gender || null;
this.FirstNameAlt = data.FirstNameAlt || null;
this.MiddleNameAlt = data.MiddleNameAlt || null;
this.LastNameAlt = data.LastNameAlt || null;
this.FirstNameAltFound = data.FirstNameAltFound || null;
this.LastNameAltFound = data.LastNameAltFound || null;
this.GenderAlt = data.GenderAlt || null;
this.RelatedNames = data.RelatedNames || null;
this.IsCorrectedName = data.IsCorrectedName || null;
this.IsBusinessName = data.IsBusinessName || null;
this.BusinessName = data.BusinessName || null;
this.VulgarityScore = data.VulgarityScore || null;
this.CelebrityScore = data.CelebrityScore || null;
this.BogusScore = data.BogusScore || null;
this.GarbageScore = data.GarbageScore || null;
this.FirstNameDictionaryScore = data.FirstNameDictionaryScore || null;
this.MiddleNameDictionaryScore = data.MiddleNameDictionaryScore || null;
this.LastNameDictionaryScore = data.LastNameDictionaryScore || null;
this.OverallNameScore = data.OverallNameScore || null;
this.IsNameGood = data.IsNameGood || null;
this.StatusCodes = data.StatusCodes || null;
this.Status = data.Status || null;
}
toString() {
return `{BestGuessName: ${this.BestGuessName ? this.BestGuessName.toString() : 'null'}\n` +
`NameIn: ${this.NameIn}\n` +
`NameClassification: ${this.NameClassification}\n` +
`Prefix: ${this.Prefix}\n` +
`FirstName: ${this.FirstName}\n` +
`MiddleName: ${this.MiddleName}\n` +
`LastName: ${this.LastName}\n` +
`Suffix: ${this.Suffix}\n` +
`FirstNameFound: ${this.FirstNameFound}\n` +
`IsCommonFirstName: ${this.IsCommonFirstName}\n` +
`FirstNameOrigin: ${this.FirstNameOrigin}\n` +
`FirstNameSimilar: ${this.FirstNameSimilar}\n` +
`LastNameFound: ${this.LastNameFound}\n` +
`IsCommonLastName: ${this.IsCommonLastName}\n` +
`LastNameOrigin: ${this.LastNameOrigin}\n` +
`LastNameSimilar: ${this.LastNameSimilar}\n` +
`Gender: ${this.Gender}\n` +
`FirstNameAlt: ${this.FirstNameAlt}\n` +
`MiddleNameAlt: ${this.MiddleNameAlt}\n` +
`LastNameAlt: ${this.LastNameAlt}\n` +
`FirstNameAltFound: ${this.FirstNameAltFound}\n` +
`LastNameAltFound: ${this.LastNameAltFound}\n` +
`GenderAlt: ${this.GenderAlt}\n` +
`RelatedNames: ${this.RelatedNames}\n` +
`IsCorrectedName: ${this.IsCorrectedName}\n` +
`IsBusinessName: ${this.IsBusinessName}\n` +
`BusinessName: ${this.BusinessName}\n` +
`VulgarityScore: ${this.VulgarityScore}\n` +
`CelebrityScore: ${this.CelebrityScore}\n` +
`BogusScore: ${this.BogusScore}\n` +
`GarbageScore: ${this.GarbageScore}\n` +
`FirstNameDictionaryScore: ${this.FirstNameDictionaryScore}\n` +
`MiddleNameDictionaryScore: ${this.MiddleNameDictionaryScore}\n` +
`LastNameDictionaryScore: ${this.LastNameDictionaryScore}\n` +
`OverallNameScore: ${this.OverallNameScore}\n` +
`IsNameGood: ${this.IsNameGood}\n` +
`StatusCodes: ${this.StatusCodes}\n` +
`Status: ${this.Status}\n`;
}
}
class Error {
constructor(data = {}) {
this.Type = data.Type || null;
this.TypeCode = data.TypeCode || null;
this.Desc = data.Desc || null;
this.DescCode = data.DescCode || null;
}
toString() {
return `Type: ${this.Type}\n` +
`TypeCode: ${this.TypeCode}\n` +
`Desc: ${this.Desc}\n` +
`DescCode: ${this.DescCode} `;
}
}
class NameInfoV2Response {
constructor(data = {}) {
this.NameInfoV2 = data.NameInfoV2 ? new NameInfoV2(data.NameInfoV2) : null;
this.Error = data.Error ? new Error(data.Error) : null;
}
toString() {
return `NameInfoV2: ${(this.NameInfoV2 ? this.NameInfoV2.toString() : 'null')}\n` +
`Error: ${this.Error ? this.Error.toString() : 'null'}`;
}
}
export{ NameInfoV2Response };