fiat - 6 months ago 43

C# Question

I need some modern C# code to check an Australian Business Number (ABN) is valid.

The requirements loosely are

- ABN has been user entered
- Spaces at any point to make the number readable are allowed
- If any other characters besides digits and spaces are included - validation should fail even if there is a legal sequence of digits included
- This check is a precursor to calling the ABN search webservice which will save calls with obviously bad input

Exact rules to validate the number are specified at abr.business.gov.au which are omitted here for the sake of brevity and clarity. The rules will not change over time.

Answer

This is based on Nick Harris's sample but cleaned up to use modern C# idioms

```
/// <summary>
/// http://stackoverflow.com/questions/38781377
/// 1. Subtract 1 from the first (left) digit to give a new eleven digit number
/// 2. Multiply each of the digits in this new number by its weighting factor
/// 3. Sum the resulting 11 products
/// 4. Divide the total by 89, noting the remainder
/// 5. If the remainder is zero the number is valid
/// </summary>
public bool IsValidAbn(string abn)
{
abn = abn?.Replace(" ", ""); // strip spaces
int[] weight = { 10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
int weightedSum = 0;
//0. ABN must be 11 digits long
if (string.IsNullOrEmpty(abn) || !Regex.IsMatch(abn, @"^\d{11}$"))
{
return false;
}
//Rules: 1,2,3
for (int i = 0; i < weight.Length; i++)
{
weightedSum += (int.Parse(abn[i].ToString()) - (i == 0 ? 1 : 0)) * weight[i];
}
//Rules: 4,5
return weightedSum % 89 == 0;
}
```

Bonus xUnit tests to keep your tech lead happy...

```
[Theory]
[InlineData("33 102 417 032", true)]
[InlineData("29002589460", true)]
[InlineData("33 102 417 032asdfsf", false)]
[InlineData("444", false)]
[InlineData(null, false)]
public void IsValidAbn(string abn, bool expectedValidity)
{
var sut = GetSystemUnderTest();
Assert.True(sut.IsValidAbn(abn) == expectedValidity);
}
```