The Global Exchange .NET API was designed to integrate seamlessly with the existing .NET framework, more specifically, with the CultureInfo, RegionInfo, and IPAddress classes. The CultureInfo class provides information about a culture. The RegionInfo class provides information about a country/region. The IPAddress class provides an Internet Protocol (IP) address.

The API adds another related class named Currency. The Currency class provides information about a currency, and supports exchanging money to other currencies using the Money class. The Money class provides sophisticated custom formatting capabilities, allowing an amount of money to be displayed exactly as the user expects. Money is directly comparable if the currency is the same; otherwise, use the MoneyComparer class to compare them.


To use the Global Exchange API in your Visual Studio project, run the following command in the Package Manager Console.

PM> Install-Package GlobalExchangeApi

The Currency Class

The Currency class represents a single currency uniquely identified by an ISO 4217 currency code. Besides providing general information about the currency, it also supports exchanging money to other currencies using the current exchange rate.


Currencies are constructed from a three-digit or three-character ISO 4217 currency code, a two-character ISO 3166 country code, a culture name, a RegionInfo country, a CultureInfo culture, or an IPAddress related to a country.


Currency constructors:

// public Currency(string identifier)
Currency usd = new Currency("USD");    // ISO 4217 currency code
Currency usCode = new Currency("US");  // ISO 3166 country code
Currency enUS = new Currency("en-US"); // Culture name

// public Currency(int identifier)
Currency usNumber = new Currency(840); // ISO 4217 currency number

// public Currency(RegionInfo region)
RegionInfo region = new RegionInfo("GB");
Currency fromRegionInfo = new Currency(region);

// public Currency(CultureInfo culture)
CultureInfo culture = new CultureInfo("en-US");
Currency fromCultureInfo = new Currency(culture);
// public Currency(IPAddress ipAddress)
IPAddress ipAddress = IPAddress.Parse("");
Currency fromIpAddress = new Currency(ipAddress);

Implicit Conversion

To facilitate a more natural use of the Currency class implicit type conversions from int and string to Currency have been defined. That means that you in place of a Currency object you may use three-digit or three-character ISO 4217 currency code instead. The corresponding Currency object will be created on the fly.


Implicit Currency conversion:

// public static implicit operator Currency(string identifier)
Money currencyString1 = new Money(123.45M, new Currency("USD"));
Money currencyString2 = new Money(123.45M, "USD");  //Equivalent

Money countryString1 = new Money(123.45M, new Currency("US"));
Money countryString2 = new Money(123.45M, "US");    //Equivalent

// public static implicit operator Currency(int identifier)
Money currencyNumber1 = new Money(123.45M, new Currency(840));
Money currencyNumber2 = new Money(123.45M, 840);    //Equivalent

Exchanging Money

Call the Exchange method to convert amounts of money between currencies.

See example

The Money Class

The Money Class represents an amount of money in a specific currency. The money can be exchanged to other currencies. Additionally, the class provides extensive formatting capabilities.


The Money class only has a the single constructor Money(decimal, Currency), but because of the implicit type converters defined in the Currency class, Money objects can be created from a three-digit or three-character ISO 4217 currency code, a two-character ISO 3166 country code, or a culture name as well.


Construction of Money:

Currency usdCurrency = new Currency("USD");

// public Money(decimal amount, Currency currency)
Money usd1 = new Money(100, usdCurrency);

// Implicit conversion
Money usd2 = new Money(100, "US");    // ISO 3166 country code
Money usd3 = new Money(100, "USD");   // ISO 4217 currency code
Money usd4 = new Money(100, "en-US"); // Culture name
Money usd5 = new Money(100, 840);     // ISO 4217 currency number

Exchanging Money

Call the Exchange method to convert the money to another currency.

See example

Formatting Money

A single culture normally determines how String.Format formats objects like dates and numbers. If not specified otherwise through an optional System.IFormatProvider argument, the CultureInfo.CurrentCulture property defines this culture.

The string formatting of money is more complex, because the culture associated with the currency must also be taken into account. The AssociatedCulture property of the Currency defines this culture. AssociatedCulture can be set to any culture that uses the currency.

Additionally, currency symbol formatting, negative amount formatting, and decimal number formatting determines the string representation of money.

The format string is a three-letter [a-f][a-c][a-b] code, each letter specifying a different part of how the money should be formatted.

  1. Currency Symbol Formatting [a-f]
  2. The currency symbol of the formatted string is either a currency symbol ($, €, kr.) or a three-character ISO 4217 currency code (USD, EUR, DKK), and is either prefixed or postfixed.

    1. Currency symbol from AssociatedCulture.
    2. Currency symbol from formatProvider (¤).
    3. Prefix or postfix the currency code as custom for AssociatedCulture.
    4. Prefix or postfix the currency code as custom for formatProvider.
    5. Prefix the currency code.
    6. Postfix the currency code.
  3. Negative Amount Formatting [a-c]
  4. Some cultures enclose negative numbers in parenthesis when doing accounting. Others always uses the negative sign to represent negative numbers.

    1. Accounting formatting as specified by AssociatedCulture.
    2. Accounting formatting as specified by formatProvider.
    3. Negative sign formatting.
  5. Decimal Number Formatting [a-b]
  6. The amount formatted as specified by the NumberFormatInfo of the culture. Besides a range of predefined format codes, the format argument allows formatting of the string representation of money as follows:

    1. Decimal formatting as specified by AssociatedCulture.
    2. Decimal formatting as specified by formatProvider.


Testing string Money.ToString(string format, IFormatProvider formatProvider). The current culture is set to "da-DK":

public void TestToStringCustomFormatters()
    Money dollars = new Money(1234.56M, "USD");
    Money kroner = new Money(1234.56M, "DKK");
    Money ndollars = new Money(-1234.56M, "USD");
    Money nkroner = new Money(-1234.56M, "DKK");
    CultureInfo us = CultureInfo.CreateSpecificCulture("en-US");
    CultureInfo dk = CultureInfo.CreateSpecificCulture("da-DK");

    // Set default formatProvider to "da-DK"
    Thread.CurrentThread.CurrentCulture = dk;

    Assert.AreEqual("kr. 1,234.56", kroner.ToString("aab", us));
    Assert.AreEqual("$1.234,56", dollars.ToString("aab"));
    Assert.AreEqual("kr. -1,234.56", nkroner.ToString("aab", us));
    Assert.AreEqual("($1.234,56)", ndollars.ToString("aab"));

    Assert.AreEqual("kr. 1.234,56", kroner.ToString("aba", us));
    Assert.AreEqual("$1,234.56", dollars.ToString("aba"));
    Assert.AreEqual("(kr. 1.234,56)", nkroner.ToString("aba", us));
    Assert.AreEqual("-$1,234.56", ndollars.ToString("aba"));

    Assert.AreEqual("¤1,234.56", kroner.ToString("bab", us));
    Assert.AreEqual("¤1.234,56", dollars.ToString("bab"));
    Assert.AreEqual("-¤1,234.56", nkroner.ToString("bab", us));
    Assert.AreEqual("(¤1.234,56)", ndollars.ToString("bab"));

    Assert.AreEqual("¤1.234,56", kroner.ToString("bca", us));
    Assert.AreEqual("¤1,234.56", dollars.ToString("bca"));
    Assert.AreEqual("-¤1.234,56", nkroner.ToString("bca", us));
    Assert.AreEqual("-¤1,234.56", ndollars.ToString("bca"));

    Assert.AreEqual("1,234.56 DKK", kroner.ToString("ccb", us));
    Assert.AreEqual("USD 1.234,56", dollars.ToString("ccb"));
    Assert.AreEqual("-1,234.56 DKK", nkroner.ToString("ccb", us));
    Assert.AreEqual("USD -1.234,56", ndollars.ToString("ccb"));

    Assert.AreEqual("DKK 1,234.56", kroner.ToString("dcb", us));
    Assert.AreEqual("1.234,56 USD", dollars.ToString("dcb"));
    Assert.AreEqual("DKK -1,234.56", nkroner.ToString("dcb", us));
    Assert.AreEqual("-1.234,56 USD", ndollars.ToString("dcb"));

    Assert.AreEqual("DKK 1,234.56", kroner.ToString("ecb", us));
    Assert.AreEqual("USD 1.234,56", dollars.ToString("ecb"));
    Assert.AreEqual("DKK -1,234.56", nkroner.ToString("ecb", us));
    Assert.AreEqual("USD -1.234,56", ndollars.ToString("ecb"));

    Assert.AreEqual("1,234.56 DKK", kroner.ToString("fcb", us));
    Assert.AreEqual("1.234,56 USD", dollars.ToString("fcb"));
    Assert.AreEqual("-1,234.56 DKK", nkroner.ToString("fcb", us));
    Assert.AreEqual("-1.234,56 USD", ndollars.ToString("fcb"));

If no format is specified or is G the format is dcb, i.e., prefix or postfix the currency code as custom for formatProvider, negative sign formatting, and decimal formatting as specified by formatProvider.

The default behavior is to display as many decimals as is defined for the currency. To override this behavior, append the format string with a count of decimals.


Setting the count of decimals:

public void TestToStringDecimals()
    Money kroner = new Money(1234.5678M, "DKK");
    CultureInfo us = CultureInfo.CreateSpecificCulture("en-US");

    // Set default formatProvider to "en-US"
    Thread.CurrentThread.CurrentCulture = us;

    Assert.AreEqual("DKK 1,234.57", kroner.ToString());
    Assert.AreEqual("DKK 1,235", kroner.ToString("0"));
    Assert.AreEqual("DKK 1,235", kroner.ToString("G0"));
    Assert.AreEqual("DKK 1,234.6", kroner.ToString("G1"));
    Assert.AreEqual("DKK 1,234.57", kroner.ToString("G2"));
    Assert.AreEqual("DKK 1,234.568", kroner.ToString("G3"));

Additionally, the Money format string can be embedded into a longer string format when using String.Format.


Formatting money using String.Format:

public void TestToStringInString()
    CultureInfo us = CultureInfo.CreateSpecificCulture("en-US");
    Money kroner = new Money(1234.5678M, "DKK");
    string customer = "John Doe";

    string result = string.Format(us, "Hello {0}, we have deposited {1:G0} into your bank account", customer, kroner);
    Assert.AreEqual("Hello John Doe, we have deposited DKK 1,235 into your bank account", result);

Comparing Money

The Money class implements both IComparable<Money> and IEquatable<Money> allowing Money to be sorted correctly. First, the Currency.ThreeLetterCurrencyCode properties are compared. If they are equal then the Amount properties are compared. To compare the fiscal value of the amount use the MoneyComparer class.

The MoneyComparer Class

The MoneyComparer class compares the USD value of the compared money. The class implements the IComparer<Money> interface. This interface is used with the List<T>.Sort and List<T>.BinarySearch methods.


Sort money by their fiscal value:

public void TestMoneyComparer()
    Money dkk = new Money(11, "DKK");
    Money usd = new Money(10, "USD");
    Money eur = new Money(5, "EUR");
    List<Money> moneyList = new List<Money>();


    IComparer<Money> comparer = new MoneyComparer();

    Assert.AreEqual(dkk, moneyList[1]);
    Assert.AreEqual(eur, moneyList[2]);
    Assert.AreEqual(usd, moneyList[3]);

Exchanging Money

Both the Currency class and the Money class exposes the method Exchange, which exchanges money from one currency to another using the current exchange rate. Exchange rates are fetched from the Global Exchange API server, but are cached locally, so there is no round trip to the server when exchanging money.


Three equivalent methods to convert 100 USD (US dollar) to COP (Colombian peso):

// public static Money Exchange(decimal fromAmount, Currency fromCurrency, Currency toCurrency)
Money peso1 = Currency.Exchange(100, "USD", "COP");

// public Money Exchange(decimal fromAmount, Currency fromCurrency)
Currency usdCurrency = new Currency("USD");
Money peso2 = usdCurrency.Exchange(100, "COP");

// public Money Exchange(Currency toCurrency)
Money usd = new Money(100, "USD");
Money peso3 = usd.Exchange("COP");

Extension Methods

Through extensions methods, the Global Exchange .NET API effectively adds IP to country lookup and currency information to the IPAddress, CultureInfo, and RegionInfo classes of the .NET framework.


The API adds the extension methods GetCurrency() and GetRegion() to the IPAddress class. The IP to country lookup table is cached locally, so there is no round trip to the server.


Get currency and region from a danish IP address:

public void ExtensionMethods_IPAddress()
    IPAddress ipAddress = IPAddress.Parse("");
    // public static Currency GetCurrency(this IPAddress ipAddress)
    Currency currency = ipAddress.GetCurrency();

    // public static RegionInfo GetRegion(this IPAddress ipAddress)
    RegionInfo region = ipAddress.GetRegion();

    Assert.AreEqual("DKK", currency.ThreeLetterCurrencyCode);
    Assert.AreEqual("DK", region.Name);


The extension method GetCurrency() has been added to the RegionInfo class.


Get the currency of Great Britain:

public void ExtensionMethods_RegionInfo()
    RegionInfo region = new RegionInfo("GB");
    // public static Currency GetCurrency(this RegionInfo regionInfo)
    Currency currency = region.GetCurrency();

    Assert.AreEqual("GBP", currency.ThreeLetterCurrencyCode);


Similarly, the extension method GetCurrency() has been added to the CultureInfo class.


Get the currency of the American English culture:

public void ExtensionMethods_CultureInfo()
    CultureInfo culture = new CultureInfo("en-US");
    // public static Currency GetCurrency(this CultureInfo cultureInfo)
    Currency currency = culture.GetCurrency();

    Assert.AreEqual("USD", currency.ThreeLetterCurrencyCode);


The first month is free. After the first month, you must subscribe to the API to get a subscription token. If you require less than 1000 request/month the API continues to be free. Just make a free subscription.

The subscription token must be added with key GlobalExchangeApi_SubscriptionToken to the <appSettings/> element of your app.config/web.config file.


Set GlobalExchangeApi_SubscriptionToken configuration key in app.config or web.config:

    <add key="GlobalExchangeApi_SubscriptionToken" value="CTS4CNLDL5V59PT4" />

If modifying your app.config/web.config file is not appropriate, the subscription token can also be set on the data providers requesting data from the Global Exchange API server.

The subscription token is used when looking up IP addresses and requesting currency exchange rates, each having a corresponding data provider. IP address lookups is performed by LiveIPLookupProvider.Instance. Exchange rates are retrieved by LiveExchangeRateProvider.Instance.


Set SubscriptionToken of the Global Exchange API data providers:

LiveIPLookupProvider.Instance.SubscriptionToken = "CTS4CNLDL5V59PT4";
LiveExchangeRateProvider.Instance.SubscriptionToken = "CTS4CNLDL5V59PT4";